diff --git a/.eslintignore b/.eslintignore index f391acf72..04fb617de 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,8 @@ helix-importer-ui -tools/sitemap -solutions/plugins/experimentation -solutions/vendor +_src/scripts/lib-franklin-api.js +_src/scripts/vendor +_src/vendor +_src/plugins +_src/scripts/libs/** +_src/scripts/utils/bot-prevention.js +tools diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..3f4db9dbb --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# @global-owner1 and @global-owner2 will be requested for +# review when someone opens a pull request. +* @enake diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index bd93f8e30..5dc84d4e3 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -3,5 +3,5 @@ Please always provide the [GitHub issue(s)](../issues) your PR is for, as well a Fix # Test URLs: -- Before: https://main--bitdefender--hlxsites.hlx.page/solutions/ -- After: https://--bitdefender--hlxsites.hlx.page/solutions/ \ No newline at end of file +- Before: https://main--www-websites--bitdefender.hlx.page/zh-hk/ +- After: https://--www-websites--bitdefender.hlx.page/zh-hk/ diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index 0b534167e..24ae18ff2 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -16,20 +16,20 @@ jobs: - name: Use node.js uses: actions/setup-node@v3 with: - node-version: '16' #required for npm 8 or later. + node-version: '20' #required for npm 8 or later. - run: npm install - run: npm run lint env: CI: true - ghost_inspector_tests: - needs: linting - runs-on: ubuntu-latest - steps: - - name: execute Ghost Inspector test - uses: docker://ghostinspector/cli - with: - args: suite execute ${{ secrets.GI_SUITE }} \ - --apiKey ${{ secrets.GI_API_KEY }} \ - --branchName ${{ env.BRANCH_NAME }} \ - --errorOnFail \ - --errorOnScreenshotFail + # ghost_inspector_tests: + # needs: linting + # runs-on: ubuntu-latest + # steps: + # - name: execute Ghost Inspector test + # uses: docker://ghostinspector/cli + # with: + # args: suite execute ${{ secrets.GI_SUITE }} \ + # --apiKey ${{ secrets.GI_API_KEY }} \ + # --branchName ${{ env.BRANCH_NAME }} \ + # --errorOnFail \ + # --errorOnScreenshotFail diff --git a/.gitignore b/.gitignore index 498dc186f..21145c2f9 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ helix-importer-ui .vscode/* tools/sitemap/node_modules/* + +.env \ No newline at end of file diff --git a/404.html b/404.html index 165f8c43b..0691fefe3 100644 --- a/404.html +++ b/404.html @@ -9,12 +9,15 @@ - + - + + - + @@ -146,7 +149,7 @@

Page Not Found

The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.

+
diff --git a/solutions/blocks/accordion/accordion.css b/_src/blocks/accordion/accordion.css similarity index 78% rename from solutions/blocks/accordion/accordion.css rename to _src/blocks/accordion/accordion.css index 758603d83..7916b0ba6 100644 --- a/solutions/blocks/accordion/accordion.css +++ b/_src/blocks/accordion/accordion.css @@ -2,13 +2,23 @@ padding: 0 var(--body-padding); } +.accordion-container > .default-content-wrapper:last-of-type p.info-button-container a { + display: flex; + text-align: center; + margin-top: 2em; +} + +.accordion-container > .default-content-wrapper:last-of-type p.info-button-container a::before { + margin-right: 5px; +} + .accordion { cursor: pointer; } .accordion .accordion-item { margin: 16px 0; - padding: 18px 54px; + padding: 1em 2em; border-radius: 10px; border-color: rgb(229 231 235); border-width: 0; @@ -82,6 +92,7 @@ .accordion-item-content ul { padding-left: 20px; + margin-top: 5px; } .accordion-item-content li { @@ -92,9 +103,15 @@ } .accordion-item-content p { - font-size: 16px; + color: #3c3c3c; + font-size: var(--body-font-size-m); word-break: break-word; max-width: 1110px; + margin-top: 5px; +} + +.accordion-item-content p strong { + color: #3c3c3c; } .accordion-item.expanded .accordion-item-content { @@ -108,9 +125,12 @@ } @media (min-width: 992px) { /* desktop */ - .accordion .accordion-item-header h3 { - font-size: var(--heading-font-size-s); + font-size: var(--body-font-size-xl); + } + + .accordion.smaller-text .accordion-item-content p { + font-size: var(--body-font-size-s)!important; } .accordion.terms-of-use .accordion-item-header h3 { @@ -129,7 +149,6 @@ max-width: var(--section-large-desktop-max-width); padding: 0 var(--section-large-desktop-padding); } - } .accordion.faq .accordion-item, @@ -162,3 +181,21 @@ margin-bottom: 0; } +@media (max-width: 500px) { + .accordion .accordion-item { + padding: 1em; + } +} + +@media (max-width: 768px) { + .accordion-item-content p { + font-size: var(--body-font-size-s); + } +} + +@media (max-width: 992px) { + .accordion-container .default-content-wrapper { + padding-top: 0; + padding-bottom: 0; + } +} \ No newline at end of file diff --git a/solutions/blocks/accordion/accordion.js b/_src/blocks/accordion/accordion.js similarity index 100% rename from solutions/blocks/accordion/accordion.js rename to _src/blocks/accordion/accordion.js diff --git a/solutions/blocks/awards-search/awards-search.css b/_src/blocks/awards-search/awards-search.css similarity index 98% rename from solutions/blocks/awards-search/awards-search.css rename to _src/blocks/awards-search/awards-search.css index d9fb85468..ec750ecad 100644 --- a/solutions/blocks/awards-search/awards-search.css +++ b/_src/blocks/awards-search/awards-search.css @@ -102,8 +102,8 @@ main .section .awards-search .awards-results-container .award-item-container h2 width: 1.5rem; height: 1.3125rem; /* stylelint-disable-next-line property-no-vendor-prefix */ - -webkit-mask: url('/solutions/icons/arrow-right.svg'); - mask: url('/solutions/icons/arrow-right.svg'); + -webkit-mask: url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); background-color: var(--read-more-text-color); display: inline-block; opacity: 1; diff --git a/solutions/blocks/awards-search/awards-search.js b/_src/blocks/awards-search/awards-search.js similarity index 100% rename from solutions/blocks/awards-search/awards-search.js rename to _src/blocks/awards-search/awards-search.js diff --git a/_src/blocks/awards/awards.css b/_src/blocks/awards/awards.css new file mode 100644 index 000000000..9d0a150b5 --- /dev/null +++ b/_src/blocks/awards/awards.css @@ -0,0 +1,254 @@ +/* stylelint-disable no-descending-specificity */ +.awards-container { + display: flex; + justify-content: center; +} + +.awards-wrapper { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + max-width: 1300px; +} + +.awards-container .block.awards-component { + background-color: #edf9ff; + display: flex; + flex-direction: column; + align-items: center; + border-radius: 20px; +} + +.awards-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.awards-component { + display: flex; + justify-content: center; + align-items: center; + padding-top: 22px; + padding-bottom: 24px; + width: 100%; +} + +.awards-container h3 { + font-size: 32px; +} + +.awards-container h4 { + margin-bottom: 18px; + font-weight: normal; +} + +.awards-container .block.awards-component > div { + text-align: center; + display: flex; + align-items: center; + justify-content: center; +} + +.awards-component > div:nth-child(1) { + display: flex; + flex-direction: column; + align-items: center; + width: 85% !important; +} + +.awards-component > div:nth-child(2) { + display: flex; + flex-direction: column; + align-items: center; + width: 90%; +} + +.awards-component > div:nth-child(3) div { + display: flex; + flex-wrap: wrap; + justify-content: center; + width: 90%; + align-items: center; + gap: 4.5%; +} + + +.awards-component > div:nth-child(3) div img { + min-height: 56px; + height: auto; + max-width: 100%; + width: auto; + object-fit: contain; +} + +.awards-container .vsb picture{ + max-width: 90px; + min-width: 8%; +} + +.awards-container .vsb h3{ + margin-top: 0; + margin-bottom: 0; +} + +.awards-container .vsb p{ + margin-top: 0; + margin-bottom: 0; +} + +@media (min-width: 580px) { + .awards-component > div:nth-child(3) div { + max-width: 768px; + flex-wrap: nowrap; + } + + .vsb.awards-component > div:nth-child(3) div { + flex-wrap: wrap; + } +} + +@media (max-width: 768px) { + .awards-component > div:nth-child(3) div img { + min-height: auto; + margin: 5px 0; + } + + .awards-container h3 { + line-height: 38px; + } +} + +@media (min-width: 768px) { + .awards-component > div:nth-child(3) { + width: 95% !important; + } + + .awards-container .vsb picture{ + min-width: 100px; + } +} + +@media (min-width: 992px) { + .awards-component > div:nth-child(3) { + flex-wrap: nowrap; + justify-content: space-around; + width: 90%; + } + + .awards-wrapper .awards > div:nth-child(3) > div[data-valign="middle"] { + width: 100%; + display: flex; + justify-content: space-around; + align-items: center; + } + + .awards-component > div:nth-child(1) img { + width: 80px !important; + } + + .awards-component main .section.wide img { + height: auto; + object-fit: contain; + width: 70%; + } + + .awards-container .block.awards-component { + padding-bottom: 40px; + } + + .awards-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .awards-container .vsb picture{ + min-width: 75px; + } + + .vsb.awards-component > div:nth-child(3) div { + flex-wrap: nowrap; + } +} + +@media (min-width: 1200px) { + .awards-component { + display: flex; + justify-content: center; + align-items: center; + padding-top: 32px; + padding-bottom: 24px; + } + + .awards-container .block.awards-component { + padding-bottom: 50px; + } + + .awards-component div[data-align="center"][data-valign="middle"] img { + width: 80px; + } + + .awards-container .block.awards-component > div { + text-align: center; + display: flex; + align-items: center; + } + + .awards-component > div:nth-child(1) { + display: flex; + flex-direction: column; + align-items: center; + width: 55%; + } + + .awards-component > div:nth-child(2) { + display: flex; + flex-direction: column; + align-items: center; + width: 50% !important; + } + + .awards-component > div:nth-child(3) { + display: flex; + flex-direction: row; + justify-content: space-around; + width: 70%; + } + + .awards-component h3 { + font: normal normal bold 32px/38px Arial, sans-serif; + max-width: 726px; + margin-bottom: 0; + } + + .awards-component h4 { + font-size: 18px; + font-weight: normal; + line-height: 25px; + margin-bottom: 35px; + margin-top: 14px; + } + + .awards-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } + + .awards-container .vsb picture{ + min-width: 100px; +} +} + +@media (min-width: 1600px) { + .awards-containe.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/awards/awards.js b/_src/blocks/awards/awards.js new file mode 100644 index 000000000..58d8c2b72 --- /dev/null +++ b/_src/blocks/awards/awards.js @@ -0,0 +1,13 @@ +// eslint-disable-next-line no-unused-vars +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/banner-vsb/banner-vsb.css b/_src/blocks/banner-vsb/banner-vsb.css new file mode 100644 index 000000000..9150c61a2 --- /dev/null +++ b/_src/blocks/banner-vsb/banner-vsb.css @@ -0,0 +1,251 @@ +.banner-vsb-container, +.banner-vsb-container * { + box-sizing: border-box; +} + +.banner-vsb-container.section { + --gray-bg: rgb(246 246 246 / 100%); + --button-background-color: #eb0000; + --button-link-color: #fff; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --body-font-size-s: 16px; + --font-weight-bold: 500; + --button-hover-background-color: #d80000; + + padding: 0; +} + +/* imports from global */ +.banner-vsb-container a.button:any-link, input[type="submit"] { + font-family: var(--body-font-family); + font-size: var(--body-font-size-s); + font-style: normal; + font-weight: var(--font-weight-bold); + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: var(--button-link-color); + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.banner-vsb-container a.button:hover, +.banner-vsb-container a.button:focus, +.banner-vsb-container input[type="submit"]:hover, +.banner-vsb-container input[type="submit"]:focus { + background-color: var(--button-hover-background-color); + border: 2px solid var(--button-hover-background-color); + cursor: pointer; +} + +.banner-vsb-container a.button span.button-text { + transition: transform .2s cubic-bezier(.4,0,.2,1); + transform: translate(0, 0); +} + +.banner-vsb-container a.button:hover span.button-text { + transform: translate(-10px, 0); +} + +.banner-vsb-container a.button::after, +.banner-vsb-container input[type="submit"]::after, +.banner-vsb-container main .section.link-right a::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + opacity: 0; + margin-left: -10px; +} + +.banner-vsb-container a.button:hover::after, +.banner-vsb-container input[type="submit"]:hover::after { + transform: translateX(5px); + opacity: 1; +} + +.banner-vsb-container .banner-vsb-wrapper .block { + display: flex; + flex-direction: column; +} + +.banner-vsb-container h1 { + font: normal normal bold 32px / 36px "IBM Plex Sans", sans-serif; + color: #006EFF; +} + +.banner-vsb-container h2, +.banner-vsb-container h3, +.banner-vsb-container h4 { + font: normal normal bold 20px/24px "IBM Plex Sans", sans-serif; +} + +.banner-vsb-container p, +.banner-vsb-container div { + font: normal normal normal 20px/16px "IBM Plex Sans", sans-serif; +} + +.banner-vsb-container .rte-wrapper { + position: relative; + z-index: 4; +} + +.banner-vsb-container .video-wrapper { + height: 300px; + position: relative; +} + +.banner-vsb-container .video-wrapper video { + width: 100%; + height: 100%; + object-fit: cover; +} + +.banner-vsb-container .video-wrapper::before { + content: ''; + position: absolute; + width: 100%; + height: 100%; + background: linear-gradient(to bottom, var(--gray-bg), rgb(246 246 246 / 0%)); + z-index: 1; +} + +.banner-vsb-container .default-content-wrapper { + padding-top: 20px !important; + z-index: 4; + order: -1; +} + +.banner-vsb-container a.button:any-link:not(.modal, .primary) { + border: solid white 2px !important; + width: 100%; + justify-content: center; +} + +.banner-vsb-container.we-container { + margin: 0 auto; + max-width: 1332px; + padding: 0 20px; + position: relative; + width: 100% +} + +@media(max-width: 1599px) { + .banner-vsb-container.we-container { + max-width:1300px; + padding: 0 50px + } +} + +@media(max-width: 991px) { + .banner-vsb-container.we-container { + padding:0 20px + } +} + +.banner-vsb-container.we-container::after { + clear: both; + content: ""; + display: block +} + +.banner-vsb-container.we-container-fluid { + max-width: 100% +} + +@media (min-width: 768px) { + .banner-vsb-container.section { + border-radius: 20px; + overflow: hidden; + } + + .banner-vsb-container .video-wrapper, + .banner-vsb-container .default-content-wrapper { + width: 50%; + flex-shrink: 0; + } + + .banner-vsb-container .video-wrapper::before { + top: 0; + left: -1px; + background: linear-gradient(to right, var(--gray-bg), rgb(246 246 246 / 0%)); + } + + .banner-vsb-container .default-content-wrapper { + padding: 30px; + } + + .banner-vsb-container .banner-vsb-wrapper { + border-radius: 20px; + background: var(--gray-bg); + overflow: hidden; + } + + .banner-vsb-container .banner-vsb-wrapper .block { + flex-direction: row; + } + + .banner-vsb-container a.button:any-link:not(.modal, .primary) { + width: unset; + justify-content: unset; + display: inline-flex; + margin-right: 15px; + } +} + +@media (min-width: 992px) { + .banner-vsb-container h1 { + font: normal normal bold 48px/55px "IBM Plex Sans", sans-serif; + } + + .banner-vsb-container h2, + .banner-vsb-container h3, + .banner-vsb-container h4 { + font: normal normal bold 40px/52px "IBM Plex Sans", sans-serif; + } + + .banner-vsb-container { + height: 422px; + } + + .banner-vsb-container .banner-vsb-wrapper { + height: 100%; + } + + .banner-vsb-container .banner-vsb-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .banner-vsb-container .rte-wrapper { + width: 100%; + } + + .banner-vsb-container .video-wrapper { + height: 100%; + } + + .banner-vsb-container .default-content-wrapper { + padding-top: 0 !important; + height: 100%; + display: flex; + align-items: center; + } +} diff --git a/_src/blocks/banner-vsb/banner-vsb.js b/_src/blocks/banner-vsb/banner-vsb.js new file mode 100644 index 000000000..6b1a3b52a --- /dev/null +++ b/_src/blocks/banner-vsb/banner-vsb.js @@ -0,0 +1,74 @@ +import { decorateButtons } from '../../scripts/lib-franklin.js'; + +export default async function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const [rte, videoUrlEl] = [...block.children]; + + const videoUrl = videoUrlEl.textContent.trim(); + const videoFormat = videoUrl.split('.').pop(); + + // const blockDataset = getDatasetFromSection(block); + const { videoPlayerSettings, videoPlayerPoster } = block.closest('.section').dataset; + + function appendPreloadedVideo() { + const linkVideoEl = document.createElement('link'); + const linkVideoPosterEl = document.createElement('link'); + linkVideoEl.rel = 'preload'; + linkVideoEl.as = 'video'; + linkVideoEl.href = videoUrl; + linkVideoEl.type = `video/${videoFormat}`; + + linkVideoPosterEl.rel = 'preload'; + linkVideoPosterEl.as = 'image'; + linkVideoPosterEl.href = videoPlayerPoster; + + document.head.prepend(linkVideoPosterEl); + document.head.prepend(linkVideoEl); + } + + appendPreloadedVideo(); + + const formattedVideoSettings = videoPlayerSettings + .split(',') + .map((item) => { + let newStr = item; + if (newStr.includes('=')) { + newStr = item.replace('=', '="'); + newStr = `${newStr}"`; + + return newStr; + } + + return newStr.trim(); + }) + .join(' '); + + block.innerHTML = ` +
+ +
+
+ ${rte.innerHTML} +
+ `; + + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); + + decorateButtons(block); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/solutions/blocks/barchart/barchart.css b/_src/blocks/barchart/barchart.css similarity index 70% rename from solutions/blocks/barchart/barchart.css rename to _src/blocks/barchart/barchart.css index 5564293f4..41fa391e8 100644 --- a/solutions/blocks/barchart/barchart.css +++ b/_src/blocks/barchart/barchart.css @@ -1,3 +1,7 @@ +.barchart-container .default-content-wrapper h2 { + font-size: var(--heading-font-size-l); +} + .barchart > ul { color: #3c3c3c; display: grid; @@ -19,25 +23,33 @@ box-shadow: 0 3px 8px 0 rgb(0 0 0 / 10%); display: flex; flex-direction: column; - padding: 30px 20px; + padding: 1em 2em; + margin: 7px; } .barchart.block h3 { line-height: 1.25; color: var(--text-color); - font-size: var(--body-font-size-m); - font-weight: 500; - margin-top: 0; + font-size: var(--body-font-size-xl); + font-weight: var(--font-weight-bold); + margin: 0; } - .barchart-body p { line-height: 1.25; - color: var(--text-color); + color: #3c3c3c; font-size: 14px; font-weight: 400; } +.barchart-body > p:first-of-type { + margin: 7px 0 2em; +} + +.barchart-body > p:last-of-type { + margin-top: 1.5em; +} + .barchart-body ul { display: flex; flex-wrap: wrap; @@ -58,14 +70,14 @@ font-weight: var(--font-weight-bold); } -.barchart-body li:nth-child(odd) { +.barchart-body li:nth-child(odd) { flex: 85%; line-height: 40px; position: relative; z-index: 1; } -.barchart-body li:nth-child(even) { +.barchart-body li:nth-child(even) { flex: 10%; text-align: right; padding: 0 10px 0 0; @@ -117,10 +129,9 @@ } @media (min-width: 990px) { /* desktop */ - .barchart-wrapper { max-width: var(--section-desktop-max-width); - padding: 0 var(--section-desktop-padding); + padding: 0 var(--section-desktop-padding-vertical); margin: 0 auto; } } @@ -131,3 +142,26 @@ padding: 0 var(--section-large-desktop-padding); } } + +@media (max-width: 990px) { /* desktop */ + .barchart.block h3 { + font-size: var(--body-font-size-m); + } + + .barchart > ul > li { + padding: 1em; + } +} + +@media (max-width: 768px) { + .barchart-container .default-content-wrapper h2 { + font-size: var(--heading-font-size-s); + } +} + +@media (max-width: 500px) { /* mobile */ + .barchart-container .default-content-wrapper { + padding-top: 0; + padding-bottom: 0; + } +} diff --git a/solutions/blocks/barchart/barchart.js b/_src/blocks/barchart/barchart.js similarity index 77% rename from solutions/blocks/barchart/barchart.js rename to _src/blocks/barchart/barchart.js index e866cb18d..7c51e1cf3 100644 --- a/solutions/blocks/barchart/barchart.js +++ b/_src/blocks/barchart/barchart.js @@ -10,7 +10,9 @@ export default function decorate(block) { ul.querySelectorAll('.barchart-body').forEach((container) => { const progressBars = container.querySelectorAll('ul li:nth-child(odd)'); progressBars.forEach((progressBar) => { - const value = (parseFloat(progressBar.nextElementSibling.textContent / 6) * 100).toFixed(2); + let valueAsString = progressBar.nextElementSibling.textContent; + valueAsString = valueAsString.replace(',', '.'); + const value = (parseFloat(valueAsString / 6) * 100).toFixed(2); progressBar.style.setProperty('--bar-width', `${value}%`); }); }); diff --git a/_src/blocks/big-teaser-section/big-teaser-section.css b/_src/blocks/big-teaser-section/big-teaser-section.css new file mode 100644 index 000000000..c2fd416b1 --- /dev/null +++ b/_src/blocks/big-teaser-section/big-teaser-section.css @@ -0,0 +1,119 @@ +.big-teaser-section-container { + background: white; + color: black; +} + +.big-teaser-section-container .default-content-wrapper { + display: flex; + flex-direction: column; +} + +.big-teaser-section-container .rte { + order: 1; + margin-top: 15px; +} + +.big-teaser-section-container .rte em { + color: #006EFF; + font-style: normal; +} + +.big-teaser-section-container .imgs-wrapper { + position: relative; + height: 300px; + border-radius: 15px; + overflow: hidden; +} + +.big-teaser-section-container .main-img { + width: 100%; + height: 100%; +} + + +.big-teaser-section-container .second-img { + position: absolute; + top: 0; + right: 0; + height: 100%; +} + + +@media screen and (min-width: 768px) { + .big-teaser-section-container.pb-0 { + padding-bottom: 0; + } + + .big-teaser-section-container.pt-1 { + padding-top: 1em; + } + + .big-teaser-section.block { + position: relative; + } + + .big-teaser-section-container .wrapper { + position: relative; + display: flex; + align-items: center; + } + + .big-teaser-section.reverted .wrapper { + flex-direction: row-reverse; + } + + .big-teaser-section-container .rte { + position: relative; + z-index: 1; + } + + .big-teaser-section.reverted .wrapper .rte { + margin-right: 60px; + } + + .big-teaser-section-container .imgs-wrapper { + width: 100%; + height: 450px; + top: 0; + margin: 0; + } + + .big-teaser-section-container .imgs-wrapper::before { + content: ''; + width: 100%; + height: 100%; + display: block; + position: absolute; + } +} + +@media screen and (min-width: 992px) { + .big-teaser-section-container p { + line-height: 1.3; + } + + .big-teaser-section-container .default-content-wrapper { + flex-direction: row; + align-items: unset; + } + + .big-teaser-section-container .default-content-wrapper > * { + width: calc(50% - 60px); + flex-shrink: 0; + } + + .big-teaser-section-container .default-content-wrapper > *:last-child { + margin-right: 60px; + } + + .big-teaser-section-container .imgs-wrapper { + height: 550px; + } + + .big-teaser-section-container .rte { + display: flex; + flex-direction: column; + justify-content: center; + margin-top: unset; + } +} diff --git a/_src/blocks/big-teaser-section/big-teaser-section.js b/_src/blocks/big-teaser-section/big-teaser-section.js new file mode 100644 index 000000000..a0cb5a757 --- /dev/null +++ b/_src/blocks/big-teaser-section/big-teaser-section.js @@ -0,0 +1,38 @@ +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [richTextEl, imageOnTopEl] = [...block.children]; + + const blockDataset = getDatasetFromSection(block); + const { desktopPicture, mobilePicture } = blockDataset; + + const picture = document.createElement('picture'); + const img = document.createElement('img'); + img.setAttribute('src', `${mobilePicture}?format=webply&optimize=medium`); + img.setAttribute('alt', 'picture'); + + const desktopSource = document.createElement('source'); + desktopSource.setAttribute('media', '(min-width: 768px)'); + desktopSource.setAttribute('type', 'image/webp'); + desktopSource.setAttribute('srcset', `${desktopPicture}?format=webply&optimize=medium`); + + picture.prepend(img); + picture.prepend(desktopSource); + + block.innerHTML = ` +
+
${richTextEl.children[0].innerHTML}
+ +
+
+ ${picture.outerHTML} +
+ + ${imageOnTopEl.querySelector('picture')} +
+ ${imageOnTopEl.querySelector('picture')?.innerHTML} +
+
+
+ `; +} diff --git a/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.css b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.css new file mode 100644 index 000000000..34e3f0635 --- /dev/null +++ b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.css @@ -0,0 +1,212 @@ +/* stylelint-disable no-descending-specificity */ +.bitdef-vs-brands { + display: flex; + flex-direction: column; + align-items: center; +} + +.bitdef-vs-brands .heading-container { + text-align: center; + max-width: 420px; +} + +.bitdef-vs-brands .new-container { + display: flex; + flex-direction: column; + align-items: center; +} + +.bitdef-vs-brands-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.bitdef-vs-brands-wrapper h2 { + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper h3 { + margin-bottom: 6px; + margin-top: 5px; + font: normal normal bold 24px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper .row-2 { + margin-bottom: 22px; + font-size: 14px; +} + +.bitdef-vs-brands-wrapper .table-container { + padding: 20px; + background-color: #f8f8f8; + border-radius: 16px; + max-width: 410px; + margin-bottom: 50px; +} + +.bitdef-vs-brands-wrapper table .blue-background p { + background-color: #005bd5; + color: white; + padding: 9px; + margin-top: 4px; + margin-bottom: 4px; + font: normal normal bold 14px/14px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper table .grey-background p { + background-color: #dedede; + padding: 9px; + margin-top: 4px; + margin-bottom: 4px; + font: normal normal normal 14px/14px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper table .blue-background p:nth-child(1) { + width: 100%; + border-radius: 8px 0 0 8px; +} + +.bitdef-vs-brands-wrapper table .blue-background p:nth-child(2) { + border-radius: 0 8px 8px 0; +} + +.bitdef-vs-brands-wrapper table .grey-background p:nth-child(1) { + width: 100%; + border-radius: 8px 0 0 8px; +} + +.bitdef-vs-brands-wrapper table .grey-background p:nth-child(2) { + border-radius: 0 8px 8px 0; +} + +.bitdef-vs-brands-wrapper table .same-line { + display: flex; + animation: increaseWidth 1s forwards; + width: 0; +} + +.bitdef-vs-brands-wrapper table .same-line:nth-child(1) { + margin-right: auto; +} + +.bitdef-vs-brands-wrapper .same-line { + animation: none; +} + +.bitdef-vs-brands-wrapper .same-line.animate { + animation: increaseWidth 1s forwards; +} + +.bitdef-vs-brands .row-2 > .column-0 { + padding-bottom: 14px; + font: normal normal normal 14px/18px Arial, sans-serif; +} + +.bitdef-vs-brands .row-6 > .column-0 { + padding-top: 14px; + font: normal normal normal 12px/14px Arial, sans-serif; +} + +@keyframes increase-width-row1 { + from { + width: 0; + } + + to { + width: 95%; + } +} + +/* Keyframes for the second row animation */ +@keyframes increase-width-row2 { + from { + width: 0; + } + + to { + width: 90%; + } +} + +/* Keyframes for the third row animation */ +@keyframes increase-width-row3 { + from { + width: 0; + } + + to { + width: 85%; + } +} + +/* Apply different animations to each row */ +.bitdef-vs-brands-wrapper table .row-3 .same-line.animate-row1 { + animation: increase-width-row1 1s forwards; +} + +.bitdef-vs-brands-wrapper table .row-4 .same-line.animate-row2 { + animation: increase-width-row2 1s forwards; +} + +.bitdef-vs-brands-wrapper table .row-5 .same-line.animate-row3 { + animation: increase-width-row3 1s forwards; +} + +.bitdef-vs-brands-wrapper img { + max-width: 32px; /* Adjust as needed */ + height: auto; /* Maintain aspect ratio */ +} + +@media (min-width: 768px) { + .bitdef-vs-brands-wrapper .heading-container { + max-width: 610px; + } + + .bitdef-vs-brands-wrapper .new-container { + flex-direction: row; + gap: 3%; + justify-content: center; + } + + .bitdef-vs-brands-wrapper .table-container { + width: 340px; + } +} + +@media (min-width: 990px) { + .bitdef-vs-brands-wrapper .new-container { + flex-direction: row; + gap: 3%; + justify-content: center; + } + + .bitdef-vs-brands-wrapper .table-container { + max-width: 410px; + } + + .bitdef-vs-brands-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .bitdef-vs-brandss-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .bitdef-vs-brandss-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.js b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.js new file mode 100644 index 000000000..e42778bb7 --- /dev/null +++ b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.js @@ -0,0 +1,83 @@ +// eslint-disable-next-line no-unused-vars +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const tables = block.querySelectorAll('.bitdef-vs-brands-wrapper table'); + + tables.forEach((table) => { + const parentDiv = table.closest('div'); + + parentDiv.classList.add('table-container'); + + table.querySelectorAll('tr').forEach((row, rowIndex) => { + row.classList.add(`row-${rowIndex}`); + + if (rowIndex >= 3 && rowIndex <= 5) { + if (rowIndex === 3) row.classList.add('blue-background'); + else row.classList.add('grey-background'); + row.querySelectorAll('td').forEach((td) => { + td.classList.add('same-line'); + }); + } + + row.querySelectorAll('td').forEach((cell, cellIndex) => { + cell.classList.add(`column-${cellIndex}`); + }); + }); + }); + // Select the first div within the .bitdef-vs-brands container + const firstDiv = block.querySelector('.bitdef-vs-brands > div'); + + // Add class 'heading-container' to the first div + firstDiv.classList.add('heading-container'); + + // Create a new container div + const newContainerDiv = document.createElement('div'); + newContainerDiv.classList.add('new-container'); + + // Move the second and third divs into the new container + while (firstDiv.nextSibling) { + newContainerDiv.appendChild(firstDiv.nextSibling); + } + + // Insert the new container after the first div + const bitdefContainer = block; + bitdefContainer.insertBefore(newContainerDiv, firstDiv.nextSibling); + + // Animation + const section = block; + + const threshold = { + threshold: 0.5, // Trigger animation when 50% of the section is visible + }; + + // eslint-disable-next-line no-unused-vars, no-shadow + const observer = new IntersectionObserver(((entries, observer) => { + entries.forEach((entry) => { + if (entry.isIntersecting && !entry.target.dataset.animationTriggered) { + // Add animation class to each row based on its index + // eslint-disable-next-line no-shadow + const tables = entry.target.querySelectorAll('table'); + tables.forEach((table) => { + const rows = table.querySelectorAll('.same-line'); + rows.forEach((row, index) => { + row.classList.add(`animate-row${index + 1}`); + }); + }); + // Set dataset attribute to indicate animation has been triggered + entry.target.dataset.animationTriggered = true; + } + }); + }), threshold); + + observer.observe(section); + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/bitdefender-central/bitdefender-central.css b/_src/blocks/bitdefender-central/bitdefender-central.css new file mode 100644 index 000000000..580d5f3fa --- /dev/null +++ b/_src/blocks/bitdefender-central/bitdefender-central.css @@ -0,0 +1,476 @@ +.bitdefender-central-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1290px; + --section-desktop-padding: 20px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); +} + + +.bitdefender-central-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; +} + +.bitdefender-central.block > div { + display: grid; + grid-template-columns: 1fr; + grid-gap: 32px; +} + +.bitdefender-central-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.bitdefender-central.block > div > div { + background-color: #F8F8F8; + border-radius: 20px; + padding: 24px; +} + +.bitdefender-central.block > div > div:last-of-type { + background-color: transparent; + border-radius: 20px; + padding: 0; + display: flex; + align-items: stretch; +} + +.bitdefender-central.block > div > div:last-of-type p { + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type > p:nth-of-type(1) { + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type > p:nth-of-type(5) { + margin-bottom: 7px; +} + +.bitdefender-central.block > div > div:first-of-type h3 { + font: normal normal bold 32px/38px var(--body-font-family); + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type > p:nth-of-type(2) { + font: normal normal normal 20px/23px var(--body-font-family); + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container { + display: inline-block; + padding-right: 24px; + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type a.button { + font: normal normal bold 16px/20px var(--body-font-family); + margin-top: 24px; + padding: 14px 28px; + color: #006EFF; + background: transparent; + border: 2px solid #006EFF; + border-radius: 10px; + display: inline-block; + position: relative; + min-width: 120px; + text-decoration: none; + text-align: center; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue { + background-color: #006EFF; + color: white; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:focus { + outline: 2px solid #48C1FF; + border-radius: 13px; + outline-offset: 2px; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:hover { + padding: 14px 28px; + background: #006EFF; + color: #fff; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue:hover { + background-color: #0A53C5; + border: 2px solid #0A53C5; + color: white; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:active { + background: #0D499B; + order: 2px solid #0D499B; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue:active { + background: #0A53C5; + order: 2px solid #0A53C5; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:disabled { + background: transparent; + order: 2px solid #B7B7B7; + color: #B7B7B7; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue:disabled { + background: #E7E7E7; + order: 2px solid #B7B7B7; + color: #B7B7B7; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a span { + transition: none; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:hover span { + transform: none; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a::after { + content: ''; + width: 0; + height: 0; + margin: 0; + transition: none; +} + +.bitdefender-central.block > div > div:first-of-type ul { + list-style: none; + margin: 0; + padding: 22px 0 24px; + list-style-type: none; + border-bottom: 1px solid #D1D1D1; +} + +.bitdefender-central.block > div > div:first-of-type ul li { + margin: 0; + padding: 7px 0 0; + font: normal normal normal 16px/18px var(--body-font-family); +} + +.bitdefender-central.block img { + max-width: 100%; + width: auto; + height: auto; +} + +.modal-container .columns-wrapper img { + height: 225px; +} + +.bitdefender-central.block a.video-placeholder img { + object-fit: cover; + height: 100%; + border-radius: 20px; +} + +.bitdefender-central.block > div > div:first-of-type ul li::before { + content: url("/_src/icons/checkmark-green-circle.svg"); + display: inline-block; + width: 18px; + height: 18px; + position: relative; + top: 4px; + margin-right: 9px; +} + +.bitdefender-central.block > div > div:first-of-type .icon.icon-bd-round-thumb { + width: 64px; + height: 64px; + margin-bottom: 14px; + background-color: white; + padding: 6px; + border-radius: 16px; + display: block; +} + +.bitdefender-central.block > div > div:first-of-type .linked-image-container { + display: inline-block; + padding-right: 0; + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type .linked-image-container img { + width: 154px; + height: 46px; +} + +a.video-placeholder { + position: relative; + align-items: stretch; + display: flex; + color: var(--button-link-color); +} + +.video-placeholder .video-placeholder-play { + box-sizing: border-box; + position: absolute; + top: 50%; + left: 50%; + display: block; + transform: scale(3); + width: 1.375rem; + height: 1.375rem; + border: 0.125rem solid; + border-radius: 1.25rem; + padding: 0; + background-color: #2020e0; + border-color: #2020e0; + opacity: 0.8; + transition: opacity .3s ease-in-out; +} + +.video-placeholder:hover .video-placeholder-play { + opacity: 1; +} + +.video-placeholder .video-placeholder-play::before { + content: ''; + display: block; + box-sizing: border-box; + position: absolute; + width: 0; + height: 0.625rem; + border-top: 0.3125rem solid transparent; + border-bottom: 0.3125rem solid transparent; + border-left: 0.375rem solid; + top: 0.25rem; + left: 0.4375rem; +} + +/* modal */ +.modal-container { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: var(--modal-background-color); + z-index: 999; +} + +.modal-video-container { + display: flex; +} + +.modal-container .modal-content { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: transparent; + + /* padding: 20px 30px 30px; */ + border-radius: 8px; + + /* box-shadow: 0 3px 8px 0 rgb(0 0 0 / 10%); */ + + /* border: 1px solid #707070; */ + + /* width: 75%; */ + max-height: 90%; + overflow: visible; + opacity: 1; + animation: fade-in 0.5s ease-in-out forwards; +} + +.modal-container .modal-content .section:first-child { + border-bottom: 1px solid var(--horizontal-separator-color); + padding-bottom: 15px; +} + +.modal-container .modal-content .modal-close { + height: 30px; + width: 30px; + border: 0; + padding: 1px 1px 0 0; + border-radius: 50%; + position: absolute; + top: -20px; + right: -14px; + cursor: pointer; + transition: all .3s ease-in-out; + outline: none; +} + +.modal-container .modal-content .modal-close::before { + content: ""; + position: absolute; + top: 13px; + left: 4px; + width: 26px; + height: 2px; + background: #000; + transform: rotate(45deg); + transition: all .3s ease-in-out; +} + +.modal-container .modal-content .modal-close::after { + content: ""; + position: absolute; + top: 13px; + left: 4px; + width: 26px; + height: 2px; + background: #000; + transform: rotate(133deg); + transition: all .3s ease-in-out; +} + +.modal-container.video-modal .modal-content { + background-color: transparent; + border: none; + box-shadow: none; + padding-top: 40px; + width: 100%; + max-width: 900px; +} + +.modal-container.video-modal .modal-content .section:first-child { + border-bottom: none; +} + +.modal-container.video-modal .modal-content .modal-close { + position: absolute; + top: 0; + width: 32px; + height: 32px; + opacity: 0.3; + background-color: unset; +} + +.modal-container.video-modal .modal-content .modal-close:hover { + opacity: 1; +} + +.modal-container.video-modal .modal-content .modal-close::after, .modal-container.video-modal .modal-content .modal-close::before { + position: absolute; + content: ' '; + height: 33px; + width: 2px; + background-color: #040dfd; +} + +.modal-container.video-modal .modal-content .modal-close::after { + transform: rotate(45deg); +} + +.modal-container.video-modal .modal-content .modal-close::before { + transform: rotate(-45deg); +} + +@media (min-width: 992px) { + .bitdefender-central-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .bitdefender-central.block > div { + grid-template-columns: 1fr 1fr; + } + + .video-placeholder .video-placeholder-play { + width: 2rem; + height: 2rem; + } + + .video-placeholder .video-placeholder-play::before { + height: 1rem; + top: 0.39rem; + left: 0.625rem; + border-top: 0.5rem solid transparent; + border-bottom: 0.5rem solid transparent; + border-left: 0.7rem solid; + } + + /* .modal-container .modal-content { + padding: 52px 62px 54px 55px; + max-width: 660px; + } */ + + .modal-container .modal-content .columns-wrapper { + padding-left: 0; + padding-right: 0; + } +} + +@media (min-width: 1200px) { + .bitdefender-central-container.we-container { + max-width: 1290px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/bitdefender-central/bitdefender-central.js b/_src/blocks/bitdefender-central/bitdefender-central.js new file mode 100644 index 000000000..b4ed63589 --- /dev/null +++ b/_src/blocks/bitdefender-central/bitdefender-central.js @@ -0,0 +1,186 @@ +function embedYoutube(url, autoplay) { + const usp = new URLSearchParams(url.search); + const suffix = autoplay ? '&muted=1&autoplay=0&enablejsapi=1' : ''; + let vid = usp.get('v') ? encodeURIComponent(usp.get('v')) : ''; + const embed = url.pathname; + if (url.origin.includes('youtu.be')) { + [, vid] = url.pathname.split('/'); + } + const modalContainer = document.createElement('dialog'); + modalContainer.classList.add('modal-container'); + + const modalContent = document.createElement('div'); + modalContent.classList.add('modal-content'); + modalContainer.appendChild(modalContent); + + const closeModal = () => modalContainer.close(); + const close = document.createElement('div'); + close.classList.add('modal-close'); + modalContent.append(close); + + const iframe = document.createElement('iframe'); + iframe.width = 783; + iframe.height = 440; + iframe.src = `https://www.youtube.com${vid ? `/embed/${vid}?rel=0&v=${vid}${suffix}` : embed}`; + iframe.title = 'YouTube video player'; + iframe.frameborder = 0; + iframe.allow = 'autoplay; fullscreen; accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture'; + iframe.allowFullscreen = true; + iframe.loading = 'lazy'; + modalContent.appendChild(iframe); + close.addEventListener('click', () => { + iframe.contentWindow.postMessage('{"event":"command","func":"stopVideo","args":""}', '*'); + closeModal(); + }); + return modalContainer; + // `
+ // + //
`; +} + +function decorateLinkedPictures(main) { + main.querySelectorAll('picture').forEach((picture) => { + // this condition checks if the picture is part of some content block ( rte ) + // and not a direct element in some DIV block + // that could have different behaviour for some blocks (ex: columns ) + if (picture.closest('div.block') && picture.parentElement.tagName !== 'DIV') { + const next = picture.parentNode.nextElementSibling; + if (next) { + const a = next.querySelector('a'); + const link = a?.textContent; + /* Modal video */ + if (a && link.startsWith('https://') && link.includes('fragments')) { + a.innerHTML = ''; + a.className = 'video-placeholder'; + a.appendChild(picture); + const overlayPlayButton = document.createElement('span'); + overlayPlayButton.className = 'video-placeholder-play'; + a.appendChild(overlayPlayButton); + a.addEventListener('click', async (event) => { + event.preventDefault(); + // eslint-disable-next-line no-use-before-define + }); + const up = a.parentElement; + if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { + up.classList.add('modal-video-container'); + } + return; + } + // Basic linked image + if (a && link.startsWith('https://')) { + a.innerHTML = ''; + a.className = 'linked-image'; + const pictureParent = picture.parentNode; + a.append(picture); + if (pictureParent.children.length === 0) { + pictureParent.parentNode.removeChild(pictureParent); + } + const up = a.parentElement; + if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { + up.classList.add('linked-image-container'); + } + } + } + } + }); +} + +function decorateButtons(element) { + const wrapButtonText = (a) => ((a.innerHTML.startsWith('<')) + ? `${a.querySelector('span.icon')?.outerHTML || ''}${a.textContent}` + : `${a.textContent}${a.querySelector('span.icon')?.outerHTML || ''}` + ); + element.querySelectorAll('a').forEach((a) => { + if (a.closest('.nav-brand') || a.closest('.nav-sections')) { + return; + } + a.title = a.title || a.textContent; + if (a.href !== a.textContent) { + const up = a.parentElement; + const twoup = a.parentElement.parentElement; + const threeup = a.parentElement.parentElement?.parentElement; + + if (!a.querySelector('img')) { + // Example:

Text

+ if (up.childNodes.length === 1 && up.tagName === 'STRONG' + && twoup.childNodes.length === 1 && twoup.tagName === 'P') { + a.className = 'button primary'; + twoup.classList.add('button-container'); + up.replaceWith(a); + a.innerHTML = wrapButtonText(a); + return; + } + if (up.childNodes.length === 1 && up.tagName === 'EM' + && twoup.childNodes.length === 1 && twoup.tagName === 'STRONG' + && threeup?.childNodes.length === 1 && threeup?.tagName === 'P') { + a.className = 'button secondary'; + threeup.classList.add('button-container'); + up.replaceWith(a); + a.innerHTML = wrapButtonText(a); + return; + } + // Example:

Text (example.com)

+ if (up.childNodes.length === 1 && up.tagName === 'P' && a.href.includes('/fragments/')) { + a.className = 'button modal'; + up.classList.add('button-container'); + return; + } + // Example:

Text 50% Discount

+ if (up.childNodes.length === 3 && up.tagName === 'P' && a.nextElementSibling?.tagName === 'EM') { + a.className = 'button'; + up.classList.add('button-container'); + a.innerHTML = wrapButtonText(a); + a.dataset.modal = a.nextSibling.textContent.trim().slice(1, -1); + a.nextSibling.remove(); + return; + } + // Example:

? Text

+ if (up.childNodes.length === 1 && up.tagName === 'P' && up.innerText.startsWith('?')) { + a.className = 'info-button modal'; + up.classList.add('info-button-container'); + a.textContent = a.textContent.slice(1).trim(); + a.title = a.title.slice(1).trim(); + return; + } + // Example:

Text

+ if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { + a.className = 'button'; // default + up.classList.add('button-container'); + a.innerHTML = wrapButtonText(a); + } + } + } + }); +} + +export default async function decorate(block, options) { + const { + // eslint-disable-next-line no-unused-vars + videoUrl, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + decorateLinkedPictures(block); + decorateButtons(block); + + const wrapper = block.querySelector('.video-placeholder'); + block.appendChild(embedYoutube(new URL(videoUrl), true)); + const modalContainer = block.querySelector('dialog'); + wrapper.addEventListener('click', () => { + modalContainer.showModal(); + }); + } + const firstButton = block.querySelector('a.button'); + if (firstButton) { + firstButton.classList.add('blue'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/blog-insert/blog-insert.css b/_src/blocks/blog-insert/blog-insert.css new file mode 100644 index 000000000..689f9d1d1 --- /dev/null +++ b/_src/blocks/blog-insert/blog-insert.css @@ -0,0 +1,8 @@ +.blog-insert-container { + text-align: center; +} + +.blog-insert-container img { + width: 100%; + height: auto; +} \ No newline at end of file diff --git a/_src/blocks/blog-insert/blog-insert.js b/_src/blocks/blog-insert/blog-insert.js new file mode 100644 index 000000000..733a139fb --- /dev/null +++ b/_src/blocks/blog-insert/blog-insert.js @@ -0,0 +1,18 @@ +export default function decorate(block) { + const urlDiv = block.querySelector('div > div:nth-child(2) > div'); + const url = urlDiv.textContent.trim(); + + // Get the picture element + const pictureElement = block.querySelector('picture'); + + // Create a new anchor element + const anchorElement = document.createElement('a'); + anchorElement.href = url; + + // Wrap the picture element with the anchor element + pictureElement.parentNode.insertBefore(anchorElement, pictureElement); + anchorElement.appendChild(pictureElement); + + block.textContent = ''; + block.append(anchorElement); +} diff --git a/_src/blocks/blog-news/blog-news.css b/_src/blocks/blog-news/blog-news.css new file mode 100644 index 000000000..e8863be30 --- /dev/null +++ b/_src/blocks/blog-news/blog-news.css @@ -0,0 +1,73 @@ +.blog-news { + max-width: 1330px; + margin: 0 auto; + padding: 0 20px; +} + +.blog-news h2 { + font-size: 2rem; + margin-bottom: 10px; +} + +.blog-news .blog-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + justify-content: center; + gap: 30px; +} + +.blog-news .blog-card { + text-align: center; + overflow: hidden; + display: flex; + flex-direction: column; + align-items: center; + gap: 30px; +} + +.blog-news .blog-card img { + object-fit: cover; + background-color: #FFD6D6; + border-radius: 20px; +} + +.blog-news .blog-card p { + font-size: 1.2rem; + margin: 0; + margin-bottom: 24px; + font-weight: bold; + color: #000; +} + +.blog-news .blog-card a { + text-decoration: none; + color:#006EFF; + font-weight: bold; +} + +.blog-news .blog-card a:hover { + text-decoration: underline; +} + +.blog-news .blog-card .blog-card-content { + display: flex; + flex-direction: column; + gap: 24px; + text-align: left; +} + +@media (min-width: 1440px){ + .blog-news .blog-grid{ + grid-template-columns: repeat(3, 1fr) + } + + .blog-news .blog-card img { + width: 420px; + height: 308px; + object-fit: cover; + background-color: #FFD6D6; + border-radius: 20px; + } + +} + diff --git a/_src/blocks/blog-news/blog-news.js b/_src/blocks/blog-news/blog-news.js new file mode 100644 index 000000000..9c3a0f277 --- /dev/null +++ b/_src/blocks/blog-news/blog-news.js @@ -0,0 +1,50 @@ +import { matchHeights } from '../../scripts/utils/utils.js'; + +async function renderBlogGrid(block, endpoint, articlesNumber) { + const blogGrid = block.querySelector('.blog-grid'); + try { + const response = await fetch(endpoint); + const rssText = await response.text(); + + const data = new window.DOMParser().parseFromString(rssText, 'text/xml'); + const items = data.querySelectorAll('item'); + let currentCount = 0; + items.forEach((item) => { + // eslint-disable-next-line no-plusplus + currentCount++; + if (currentCount > articlesNumber) return; + const link = item.querySelector('link').textContent; + + const title = item.querySelector('title').textContent; + const media = item.querySelector('content'); + const image = media.getAttribute('url'); + + // Create a blog card + const blogCard = document.createElement('a'); + blogCard.setAttribute('href', link); + blogCard.classList.add('blog-card'); + + blogCard.innerHTML = ` + ${title} +
+

${title}

+ Find out more +
+ `; + + blogGrid.appendChild(blogCard); + }); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + } +} + +export default function decorate(block) { + const { endpoint, articlesNumber } = block.closest('.section').dataset; + const blogGrid = document.createElement('div'); + block.appendChild(blogGrid); + blogGrid.classList.add('blog-grid'); + renderBlogGrid(block, endpoint, articlesNumber); + matchHeights(block, 'p'); +} diff --git a/_src/blocks/box-carousel/box-carousel.css b/_src/blocks/box-carousel/box-carousel.css new file mode 100644 index 000000000..f561aeac0 --- /dev/null +++ b/_src/blocks/box-carousel/box-carousel.css @@ -0,0 +1,227 @@ +/* stylelint-disable no-descending-specificity */ +.box-carousel-container { + background: white; +} + +.box-carousel-container .carousel-header { + display: flex; + align-items: center; + justify-content: space; +} + +.box-carousel-container .carousel-header .title { + color: black; +} + +.box-carousel-container .carousel-header .title p { + margin: 0 0 16px; +} + +.box-carousel-container .carousel-header .left-arrow.disabled, +.box-carousel-container .carousel-header .right-arrow.disabled { + opacity: 0.3; +} + +.box-carousel-container .carousel-header .left-arrow, +.box-carousel-container .carousel-header .right-arrow { + color: black; +} + +.box-carousel-container .carousel-container { + width: 100%; + position: relative; + display: flex; + overflow: hidden; +} + +.box-carousel-container .carousel { + display: flex; + transition: transform 150ms cubic-bezier(0.165, 0.84, 0.44, 1) 0s; +} + +.box-carousel-container .block.scrollable .carousel { + overflow: auto; +} + +.box-carousel-container .block.scrollable .carousel::-webkit-scrollbar { + display: none; +} + +.box-carousel-container .carousel-item { + display: flex; + flex-direction: column; + width: 220px; + min-height: 220px; + margin: 10px; + box-sizing: border-box; + padding: 20px; + border-radius: 15px; + color: black; + font-size: 1em; + background: #eaf2ff; + flex-shrink: 0; + border: solid 1px black; +} + +.box-carousel-container.testimonials .carousel-item { + width: 300px; + height: 300px; + display: flex; + flex-direction: column; + border: solid 1px #ddd; + background: white; + position: relative; +} + +.box-carousel-container .carousel-item:first-child { + margin-left: 0; +} + +.box-carousel-container .carousel-item .title { + letter-spacing: 0; + overflow: hidden; + margin: 12px 0; +} + +.box-carousel-container.testimonials .carousel-item .title { + -webkit-line-clamp: 6; + line-clamp: 6; +} + +.box-carousel-container .carousel-item .subtitle { + font: normal normal normal 12px/15px "IBM Plex Sans", sans-serif; + letter-spacing: 0; + overflow: hidden; + margin-top: auto; + color: #242424; +} + +.box-carousel-container.testimonials .carousel-item .subtitle-secondary { + font: normal normal bold 14px/21px "IBM Plex Sans", sans-serif; + margin-top: auto; + position: relative; +} + +.box-carousel-container.testimonials .carousel-item .subtitle-secondary::before { + content: ''; + display: block; + position: absolute; + width: 40px; + height: 1px; + background: black; + top: -5px; +} + +.box-carousel-container.testimonials .carousel-item .subtitle { + margin-top: unset; + color: #242424; +} + +.box-carousel-container .left-arrow svg { + transform: rotate(180deg); +} + +.box-carousel-container .arrow { + width: 100px; +} + +.box-carousel-container .arrow svg { + width: 100%; + height: 50px; +} + +.box-carousel-container .arrow svg path { + fill: white; +} + +.box-carousel-container .arrow.disabled svg path { + fill: #a5a5a5; +} + +.box-carousel-container .carousel-item .icon { + width: 35px; + height: 35px; + margin: 0; +} + +.box-carousel-container svg path { + fill: black !important; +} + +.box-carousel-container.testimonials .img-container { + height: 60px; + width: 100%; +} + +.box-carousel-container.testimonials .img-container img { + object-fit: contain; + filter: grayscale(100%); + width: unset; +} + + +@media screen and (min-width: 768px) { + .box-carousel-container .carousel-header { + justify-content: space-between; + margin-bottom: 20px; + } + + .box-carousel-container.testimonials .img-container { + width: 60%; + } + + .box-carousel-container.testimonials .carousel-item { + width: calc((100% - 25px) / 2); + min-height: 390px; + } + + .box-carousel-container .carousel-item .subtitle { + font: normal normal normal 18px/23px "IBM Plex Sans", sans-serif; + } + + .box-carousel-container.testimonials .carousel-item .subtitle { + font: normal normal normal 12px/15px "IBM Plex Sans", sans-serif; + } +} + +@media screen and (min-width: 992px) { + .box-carousel-container .default-content-wrapper { + overflow: hidden; + } + + .box-carousel-container.testimonials .carousel-item { + width: calc((100% - 25px) / 3); + min-height: 390px; + } + + .box-carousel-container .carousel-item .title { + font-size: 22px; + color: #242424; + font-weight: 500; + } + + .box-carousel-container.testimonials .carousel-item .subtitle { + font-size: 17px; + } + + .box-carousel-container.testimonials .carousel-item .subtitle-secondary { + font-size: 18px; + } + + .box-carousel-container:not(.testimonials) .carousel-item:hover { + color: white; + background: #006dff; + box-shadow: 0 3px 40px #006EFFF2; + } + + .box-carousel-container .carousel-item:hover svg path { + fill: white !important; + } +} + +@media (min-width: 1600px) { + .box-carousel-container.testimonials .carousel-item { + width: calc(100% / 3); + } +} + diff --git a/_src/blocks/box-carousel/box-carousel.js b/_src/blocks/box-carousel/box-carousel.js new file mode 100644 index 000000000..25a290c95 --- /dev/null +++ b/_src/blocks/box-carousel/box-carousel.js @@ -0,0 +1,164 @@ +import { decorateIcons } from '../../scripts/lib-franklin.js'; +import { debounce, isView } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [titleEl, ...slides] = [...block.children]; + let currentSlideIndex = 0; + + const isTestimonials = block.closest('.section').classList.contains('testimonials'); + + const carouselItemStyle = { + margin: 20, + }; + + function isFirstIndex() { + return currentSlideIndex === 0; + } + + function isLastIndex() { + return currentSlideIndex === slides.length - 3; + } + + function scrollCarousel(offset, carousel) { + const carouselItem = block.querySelector('.carousel-item'); + carousel.style.transform = `translateX(${-1 * offset * (carouselItem.offsetWidth + carouselItemStyle.margin)}px)`; + } + + function getCarousel() { + return block.querySelector('.carousel'); + } + + function updateDisabledArrow() { + const leftArrowEl = block.querySelector('.left-arrow'); + const rightArrowEl = block.querySelector('.right-arrow'); + + leftArrowEl.classList.remove('disabled'); + rightArrowEl.classList.remove('disabled'); + + if (isLastIndex()) { + block.querySelector('.right-arrow').classList.add('disabled'); + return; + } + + if (isFirstIndex()) { + block.querySelector('.left-arrow').classList.add('disabled'); + } + } + + function leftArrowHandler(e) { + e.preventDefault(); + if (isFirstIndex()) { + return; + } + currentSlideIndex -= 1; + scrollCarousel(currentSlideIndex, getCarousel()); + updateDisabledArrow(currentSlideIndex); + } + + function rightArrowHandler(e) { + e.preventDefault(); + if (isLastIndex()) { + return; + } + currentSlideIndex += 1; + scrollCarousel(currentSlideIndex, getCarousel()); + updateDisabledArrow(currentSlideIndex); + } + + function renderArrows() { + block.classList.remove('scrollable'); + + if (isView('desktop')) { + const cardsNotFullyVisible = window.innerWidth > 767; + return cardsNotFullyVisible ? ` + + + + + + + + + + + + + + + ` : ''; + } + + block.classList.add('scrollable'); + return ''; + } + + function render() { + block.classList.add('default-content-wrapper'); + + block.innerHTML = ` + + + + `; + + decorateIcons(block); + + const leftArrowEl = block.querySelector('.left-arrow'); + const rightArrowEl = block.querySelector('.right-arrow'); + + if (leftArrowEl && rightArrowEl) { + leftArrowEl.removeEventListener('click', leftArrowHandler); + rightArrowEl.removeEventListener('click', rightArrowHandler); + + leftArrowEl.addEventListener('click', leftArrowHandler); + rightArrowEl.addEventListener('click', rightArrowHandler); + } + } + + render(); + + window.addEventListener('resize', debounce(render, 250)); +} diff --git a/_src/blocks/box-image-round-card/box-image-round-card.css b/_src/blocks/box-image-round-card/box-image-round-card.css new file mode 100644 index 000000000..5ac577997 --- /dev/null +++ b/_src/blocks/box-image-round-card/box-image-round-card.css @@ -0,0 +1,109 @@ +.box-image-round-card-container .inner-wrapper { + display: flex; + background-color: #fff; + border-radius: 8px; + box-shadow: 0 3px 6px 0 rgb(0 0 0 / 8%); + position: relative; + overflow: hidden; + z-index: 2; + width: 100%; + margin: 10px 0; + padding: 40px 23px 2pc; +} + +/* .box-image-round-card-container .inner-wrapper > div:nth-child(1) { */ + +/* width: 50%; */ + +/* } */ + +/* .box-image-round-card-container .inner-wrapper > div:last-child { */ + +/* border-radius: 50%; */ + +/* position: absolute; */ + +/* right: -35px; */ + +/* top: -60px; */ + +/* width: 225px; */ + +/* height: 225px; */ + +/* overflow: hidden; */ + +/* } */ + +.box-image-round-card-container .icon-apple { + width: 60px; + transform: none; +} + +.box-image-round-card-container img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform .3s ease-in-out,-webkit-transform .3s ease-in-out; + transform: scale(1); +} + +.box-image-round-card-container .inner-wrapper > a:first-child { + position: absolute; + top: 0; + left: 0; + z-index: 2; + width: 100%; + height: 100%; + text-indent: -999999px; +} + +.box-image-round-card-container .inner-wrapper p.button-container { + display: inline-block; + margin-right: 10px; +} + +@media(min-width: 767px) { + /* tablet */ + .box-image-round-card-container .inner-wrapper p { + font-size: 18px; + } + + /* .box-image-round-card-container .inner-wrapper > div:last-child { */ + + /* width: 325px; */ + + /* height: 325px; */ + + /* } */ + .box-image-round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a::after { + transform: translateX(5px); + opacity: 1; + } + + .box-image-round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a span.button-text { + transform: translate(-10px, 0); + } + + .box-image-round-card-container .inner-wrapper > a:first-child:hover ~ div img { + transform: scale(1.1); + } + + .box-image-round-card-container .default-content-wrapper { + display: flex; + } + + .box-image-round-card-container .card-wrapper { + order: 2; + flex: 60%; + display: flex; + align-items: center; + } + + .box-image-round-card-container .picture-wrapper { + order: 1; + flex: 40%; + padding-right: 25px; + margin: 10px 0; + } +} diff --git a/_src/blocks/box-image-round-card/box-image-round-card.js b/_src/blocks/box-image-round-card/box-image-round-card.js new file mode 100644 index 000000000..36322492c --- /dev/null +++ b/_src/blocks/box-image-round-card/box-image-round-card.js @@ -0,0 +1,26 @@ +import { createOptimizedPicture } from '../../scripts/lib-franklin.js'; +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default function decorate(block) { + const innerWrapper = block.children[0]; + innerWrapper.classList = 'inner-wrapper'; + + const defaultWrapper = document.createElement('div'); + defaultWrapper.classList = 'default-content-wrapper'; + + const carWrapper = document.createElement('div'); + carWrapper.classList = 'card-wrapper'; + + carWrapper.append(innerWrapper); + + const pictureWrapper = document.createElement('div'); + pictureWrapper.classList = 'picture-wrapper'; + + const blockDataset = getDatasetFromSection(block); + pictureWrapper.append(createOptimizedPicture(blockDataset.bgImage, 'title')); + + defaultWrapper.prepend(carWrapper); + defaultWrapper.append(pictureWrapper); + + block.prepend(defaultWrapper); +} diff --git a/solutions/blocks/cards/cards.css b/_src/blocks/cards/cards.css similarity index 100% rename from solutions/blocks/cards/cards.css rename to _src/blocks/cards/cards.css diff --git a/solutions/blocks/cards/cards.js b/_src/blocks/cards/cards.js similarity index 100% rename from solutions/blocks/cards/cards.js rename to _src/blocks/cards/cards.js diff --git a/_src/blocks/columns/columns.css b/_src/blocks/columns/columns.css new file mode 100644 index 000000000..de54410dc --- /dev/null +++ b/_src/blocks/columns/columns.css @@ -0,0 +1,1523 @@ +/* stylelint-disable no-descending-specificity */ +.columns-wrapper { + padding: 0 var(--body-padding); +} + +.columns-container.chat-options p { + font-size: var(--body-font-size-s) !important; +} + +.columns-container.linear-gradient h3 { + font-size: var(--heading-font-size-xl); + margin-bottom: 1em; +} + +.columns-container.linear-gradient p { + font-size: var(--body-font-size-m); +} + +.columns.benefits > p { + margin-bottom: 0; + margin-top: 0; +} + +.columns.benefits p { + font-size: var(--body-font-size-s); + line-height: 1.5; + letter-spacing: .006em; + font-weight: var(--font-weight-regular); +} + +.columns.new-v2 p { + font-size: 16px; + font-weight: 400; + line-height: 22px; +} + +.columns.medium-image-size p:has(picture) { + text-align: center; + + img { + width: 140px; + height: 144px; + } +} + +.columns.smaller-title h4 { + font-size: 16px; +} + +.columns.awards > div > div > p { + margin: 0; + padding: 0 5px; + text-align: center; +} + +.columns.video-presentation > div > div > p { + font-size: var(--body-font-size-s); +} + +.columns.carousel > div > div > p { + width: inherit; + padding: 0 50px; + text-align: center; +} + +.columns-container.video-left .columns-right-col p { + margin: 1.5em 0; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.v3_benefits .columns.benefits p { + font-size: var(--body-font-size-s); +} + +.columns-wrapper > div.grey-bck p:first-of-type { + margin: 1em 0; +} + +.v2 .columns.awards > div > div > p { + font-size: var(--body-font-size-s); +} + +.columns.awards > div > div > p:first-of-type { + margin-bottom: 24px; +} + +.section.subtitle-blue .columns.benefits p { + font-size: var(--body-font-size-s); + font-weight: 400; + letter-spacing: .006em; + line-height: 24px; +} + +.columns.awards.v2 > div > div > p:last-of-type { + margin-top: 10px; +} + +.columns.benefits h3 { + font-size: var(--heading-font-size-m); + font-weight: var(--font-weight-bold); + line-height: 1.25; +} + +.section.subtitle-blue h3 { + font-size: 1.25rem; + + --tw-text-opacity: 1; + + color: rgb(0 110 255 / var(--tw-text-opacity)); +} + +.creators .columns-container h3 { + font-weight: bold; +} + +.columns.new-v2 h3 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 25px; + font-weight: 700; + line-height: 30px; + text-align: left; + color: #006EFF; +} + +.columns.video-presentation > div > div > h3 { + font-size: var(--heading-font-size-xl); +} + +.columns > div { + display: flex; + flex-direction: column; + justify-content: center; +} + +.columns > div > div { + order: 1; +} + +.text-over-image > div > div { + height: 600px; + border-radius: 12px; + display: flex; + flex-direction: column; + color: var(--white-color); + padding: 30px; + justify-content: flex-end; + background-size: cover; + background-repeat: no-repeat; +} + +.columns.carousel > div { + flex-direction: row; + justify-content: flex-start; + gap: 22px; + height: 15px; + top: 0; +} + +.columns.benefits > div { + align-items: flex-start; +} + +/* awards styling */ +.columns.awards > div { + gap:30px; + display: flex; + flex-flow: row wrap; + align-items: center; +} + +.columns img { + width: 100%; + +} + +.dlp.columns-container img{ + width: 67%; + margin-left: auto; +} + +.dlp.columns-container h2{ + color: #006DFF; +} + +.modal-container.get-bitdefender-familypack img { + height: auto; +} + +.columns.awards > div img { + display: block; + object-fit: contain; +} + +.columns > div > .columns-img-col img { + display: block; +} + +.grey-version .columns > div > div img, .small-icons .columns > div > div img { + height: 60px; + width: auto; +} + +.small-icons-v2 .columns > div > div img { + height: 120px; + width: auto; +} + +.columns.video-presentation .linked-image-container img { + width: 150px; + height: 44px; +} + +.columns.awards.smaller-icons > div img { + width: auto; + max-width: unset; + height: 100px; +} + +.grey-version .columns > div { + display: flex; + justify-content: space-between; +} + +.columns.carousel > div > div { + flex: 1 0 33%; + margin: 10px 5px; + width: 100%; + box-sizing: border-box; +} + +.grey-version .columns > div > div { + --tw-bg-opacity: 1; + + background-color: rgb(245 245 247 / var(--tw-bg-opacity)); + border-radius: 1rem; + padding: 3em; + margin-bottom: 1em; +} + +.text-over-image > div > div:first-child { + font-size: var(--heading-font-size-s); + margin-bottom: -10px; +} + +.percent-table .columns table tr { + align-items: center; + display: flex; + justify-content: space-between; +} + +.percent-table .columns table tr td:first-of-type { + font-size: var(--heading-font-size-l); + padding-right: 1.5em; +} + +.percent-table .columns table tr td:last-of-type { + width: 220px; +} + +.grey-version .columns > div > div h4 { + font-size: var(--heading-font-size-l); +} + +.creators .columns-container p.button-container { + text-align: center; +} + +.grey-version .columns > div > div p.button-container { + margin-bottom: auto; +} + +.columns-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.columns.highlight-text.black { + background-color: var(--black-color); + padding: 25px 2pc 20px 30px; + text-align: left; + position: absolute; + width: 100%; +} + +.columns.ferrari-text > div{ + align-items: unset; +} + +.columns.ferrari-text h2{ + color:#006DFF; + font-weight: 300; +} + +.columns.ferrari-text .columns-text-col{ + font-weight: 300; +} + +.section.ferrari-quote .columns.ferrari-text .columns-text-col{ + color:#006DFF; +} + +.columns.ferrari-text .columns-text-col.button-container{ + align-self: flex-end; +} + +.section.ferrari-quote .columns.ferrari-text .columns-text-col a{ + background: none; + border: none; + color:#006DFF; + text-align: right; + text-decoration: underline; + letter-spacing: 0; + display: block; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.v2_benefits .columns-container .default-content-wrapper { + margin-bottom: 3em; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.bigger_title .columns.benefits h3 { + font-size: var(--heading-font-size-l); +} + +/* stylelint-disable-next-line selector-class-pattern */ +.v2_benefits .columns.benefits h3 { + font-size: var(--heading-font-size-l); +} + +.columns.video-presentation > div > div { + margin: 0 auto; +} + +.section.subtitle-blue h2 { + margin: 0 auto 3em; + width: 100%; + text-align: center; +} + +.columns.with-box-shadow > div > div { + padding: 0 20px; + border-right: none; + border-bottom: 2px solid var(--overlay-background-color); +} + +.columns-wrapper > div.grey-bck > div { + flex: 1; +} + +.columns-wrapper > div.grey-bck > div > div { + margin: 0!important; + flex: 0 0 50%; +} + +.columns.carousel > div:nth-child(1) { + position: relative; + left: 0; + gap: 0; + transition: transform 0.3s ease-in-out; + height: 200px; +} + +.creators .columns-container .columns > div { + justify-content: space-between; + margin-bottom: 3em; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.v2_benefits .columns.benefits > div { + gap: 35px; +} + +.v2 .columns.awards > div { + align-items: flex-start; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.v2_benefits .columns.benefits > div > div { + font-size: var(--body-font-size-m); + flex: 1; +} + +.columns.bg-image > div > div:first-child { + font-size: var(--heading-font-size-xl); + font-weight: bold; +} + +.columns.with-box-shadow > div > div:last-child { + border: none; +} + +.section.subtitle-blue .columns.benefits > div { + gap: 45px; + margin-bottom: 2em; +} + +.columns > div > .columns-img-col { + order: 0; + text-align: center; + margin-bottom: 2em; +} + +.creators .columns-container .columns > div:last-of-type { + margin-bottom: 0; +} + +.creators .columns-container h5 { + font-weight: bold; + color: #006DFF; +} + +.creators .columns-container.baby-blue-subtitles h3 { + color: #006DFF; +} + +.creators .columns-container.baby-blue-subtitles h3 br { + display: block; +} + +.creators .columns-container a.button { + height: auto; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 30px; + justify-content: center; + padding: 5px 10px; + font-size: 14px; +} + +.columns.bg-image a { + color: white +} + +.columns.new-v2 a { + color: #006EFF!important; + font-size: 18px; + text-decoration: none; + font-weight: 600; + transition: all .2s cubic-bezier(.4,0,.2,1); +} + +.green-button .button-container a { + background-color: #51a71d; + border: 2px solid #51a71d; + text-transform: uppercase; +} + +.green-button p:last-of-type a { + text-decoration: underline; + font-size: var(--body-font-size-xs); + margin: 0 10px; +} + +.columns.new-v2 a:hover { + color: #0A53C5; + transform: translateX(10px); +} + +.columns-container.chat-options p.button-container a { + background-color: transparent; + border: 2px solid black; + color: black; + white-space: normal; +} + +.columns-container.chat-options p.button-container a:hover { + background-color: black; + color: white; +} + +.columns-container.chat-options table { + width: 100%; +} + +.columns-container.chat-options table tr { + display: flex; + justify-content: space-between; +} + +.small-icons-v2 .columns > div > div.columns-img-col { + display: flex; + align-items: center; + justify-content: center; +} + +.columns.new-v2 > div > .columns-img-col img { + object-fit: contain; +} + +.columns-container.chat-options table tr td:first-of-type img { + height: 40px; +} + +.columns-container.chat-options table tr td:last-of-type img { + height: 133px; + display: none; +} + +.columns-wrapper > div.grey-bck { + background-color: #F5F5F7; + border-radius: 1em; + padding: 0; + display: flex; + overflow: hidden; +} + +.columns-wrapper > div.grey-bck h5 { + font-size: var(--heading-font-size-m); + line-height: var(--heading-font-size-l); +} + +.columns-wrapper > div.grey-bck div.columns-text-col { + padding-left: 4em; + padding-right: 1em; +} + +.section.baby-blue-bck .columns-wrapper { + background-color: #E4F2FF; +} + +.section.grey-bck .columns-wrapper { + background-color: #F5F5F7; +} + +.section.radius-corners .columns-wrapper { + border-radius: 1rem; + overflow: hidden; +} + +.section.radius-corners-10px .columns-wrapper { + border-radius: 10px; + overflow: hidden; +} + +.section.pl-0 .columns-wrapper { + padding-left: 0; +} + +.section.pr-0 .columns-wrapper { + padding-right: 0; +} + +.columns.new-v2 > div > .columns-img-col { + margin-bottom: 1em; +} + +.section.radius-corners .columns-wrapper .columns-img-col { + border-radius: 1rem; + overflow: hidden; + margin-bottom: 0; +} + +.section.radius-corners-10px .columns-wrapper .columns-img-col, +.section.radius-corners-10px .columns-wrapper .columns-img-col img { + margin-bottom: 0; + border-radius: 0; +} + +.columns .tag-dark-blue { + background-color: #007bff; + color: white; + font-size: 16px; + padding: 4px 15px; + border-radius: 16px; + display: inline-block; + vertical-align: middle; +} + +.columns-container.black-version{ + background-color: #000; + color: white; +} + +@media (min-width: 991px) { + .columns.benefits > div { + flex-direction: unset; + gap: 32px; + align-items: stretch; + } +} + +@media (min-width: 767px) { + .columns-container.space-between .columns > div { + align-items: stretch; + } + + .columns.awards-fragment > div{ + display: grid; + grid-auto-flow: row; + grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); + gap:20px; + } + + + .columns-container.chat-options .columns > div > div { + padding: 2em; + } + + .columns.highlight-text.black { + width: 520px; + right: 2.5%; + top: 15%; + border-radius: 5px; + } + + .columns.highlight-text.black.imageleft { + left: 2.5%; + } + + .percent-table .columns table tr td:first-of-type { + padding-right: 0.5em; + } + + .columns-container.space-between .columns > div > div { + display: flex; + flex-direction: column; + justify-content: space-between; + } + + .columns.ferrari-text h2{ + font-size: 45px; + } + + .columns.ferrari-text .columns-text-col{ + font-size: 30px; + } + + .section.ferrari-quote .columns.ferrari-text .columns-text-col{ + font-size: 20px; + } +} + +@media (min-width: 992px) { /* desktop */ + .columns-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .columns > div { + align-items: center; + flex-direction: unset; + gap: 32px; + } + + .columns.awards-fragment > div{ + align-items: baseline; + } + + .columns > div > div { + flex: 1; + order: unset; + } + + + .columns-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + .columns.highlight-text.black { + right: 10%; + top: 10%; + } + + .columns.highlight-text.black.imageleft { + left: 10%; + } + + .section.subtitle-blue h2 { + margin: 0 auto 3em; + width: 630px; + } + + .section.subtitle-blue h3 { + font-size: 1.25rem; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.b_mark > div { + padding: 5em 0 3em; + margin-top: 0; + } + + .columns.awards > div > div { + flex: 0; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.b_mark .columns-img-col img { + margin-top: -200px; + margin-bottom: -3em; + } + + .columns-container.chat-options .columns > div > div { + padding: 2em; + } + + .section.subtitle-blue .columns.benefits > div { + margin-bottom: 0; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.bd_woman { + margin-top: 2em; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.bd_woman h2 { + font-weight: var(--font-weight-regular); + } + + .columns > div > .columns-img-col { + margin-bottom: 1em; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.bd_woman .columns-img-col { + margin-top: -122px; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.b_mark { + margin-bottom: 5em; + } + + .columns.screenshots { + margin-top: 4em; + } + + .v2 .columns > div > .columns-text-col { + flex: 0 0 40%; + } + + .v2 .columns > div > .columns-text-col.columns-right-col { + margin-left: 4em; + } + + .columns-container.chat-options table tr td:last-of-type img { + display: block; + } + + .creators .columns-container .columns > div > div.columns-left-col, .creators .columns-container .columns > div > div.columns-right-col { + width: 45%; + flex: none; + } + + .creators .columns-container .columns > div > div.columns-img-col { + width: 50%; + flex: none; + } + + .creators .columns-container h5 { + color: #006DFF; + font: normal normal bold 32px/45px "IBM Plex Sans", sans-serif; + } + + .creators .header-mobile.columns-container h1 { + font: normal normal bold 60px/70px "IBM Plex Sans", sans-serif; + } + + .creators .header-mobile.columns-container h2 { + color: #006DFF; + font: normal normal bold 32px/45px "IBM Plex Sans", sans-serif; + margin-bottom: 0; + } + + .creators .columns-container h3 { + font: normal normal bold 60px/70px "IBM Plex Sans", sans-serif; + } + + .creators .columns-container p { + font: normal normal normal 24px/33px Arial, sans-serif; + } + + .creators .columns-container.smaller-text p { + font: normal normal normal 18px / 27px Arial, sans-serif; + } + + .creators .columns-container p.button-container { + text-align: left; + } + + .creators .columns-container a.button { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px/24px Roboto, sans-serif; + } +} + +@media (max-width: 1200px) { + /* stylelint-disable-next-line selector-class-pattern */ + .v2_benefits .columns.benefits h3 { + font-size: var(--heading-font-size-m); + margin-bottom: 10px; + } +} + +@media (min-width: 1200px) { + .columns-container.we-container { + max-width: 1350px; + padding-left: 20px; + padding-right: 20px; + } + + .columns.awards > div > div { + flex: 1; + } + + .percent-table .columns table tr td:first-of-type { + padding-right: 1.5em; + } +} + +@media (min-width: 1600px) { /* large desktop */ + .columns-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +/* Benefits columns (icon, text, description) */ +.columns.benefits > .icon { + width: unset; + max-width: 66px; + margin-bottom: 16px; +} + +.columns-container.video-left video { + width: 100%; + border-radius: 10px; +} + +.columns-container.video-left .columns-right-col { + width: 100%; + flex: none; +} + +@media (min-width: 1271px) { + .columns.benefits p { + font-size: 18px; + } +} + +/* paragraph with image */ +.columns.video-presentation .button-container { + display: inline-block; + padding-right: 0; +} + +.columns.video-presentation .linked-image-container { + display: inline-block; + padding-right: 3px; + margin-top: 0; + margin-bottom: 0; +} + +.columns.video-presentation ul { + padding-top: 1px; +} + +.columns.vpn-presentation .button-container, +.columns.vpn-presentation .info-button-container{ + display: inline-block; + padding-right: 13px; + margin-top: 13px; +} + +.columns.vpn-presentation .left-col { + margin-bottom: 40px; +} + +@media (min-width: 992px) { + .columns.vpn-presentation .left-col { + margin-bottom: 0; + } +} + +.section.bullet-points.columns-container ul { + list-style: disc; +} + +.section.migration.columns-container ul { + padding: 0; +} + +.section.migration.columns-container ul li { + display: flex; + padding-left: 0; + margin-bottom: 1em; +} + +.section.migration.columns-container ul li::before { + content: url("/_src/icons/checkmark-light-green-circle.svg"); + display: inline-block; + width: 18px; + height: 18px; + position: relative; + top: 4px; + margin-right: 9px; + flex-shrink: 0; +} + +.section.migration.columns-container .columns-img-col img { + border-radius: 10px; +} + +.columns.carousel { + width: 100%; + margin-top: 0; + overflow: hidden; + height: auto; +} + +.section.migration .columns.carousel { + margin-top: 0; + height: auto; +} + +.carousel-buttons { + position: relative; + top: 30px; + display: flex; + justify-content: center; + align-items: center; + transition: all .4s ease-in-out; +} + +.section.migration .columns.carousel .carousel-buttons { + top: -10px; +} + +.columns.carousel button { + align-items: flex-start; + width: 10px; + height: 10px; + border-radius: 100%; + margin: 10px; + padding: 0; + background-color: var(--black-color); + border: none; + cursor: pointer; +} + +.columns.carousel button:hover { + background-color: var(--link-color); +} + +.section.wide.light-sky-blue.columns-container { + height: auto; +} + +.section.white.columns-container .columns.awards > div { + flex-direction: unset; + align-items: center; +} + +.section.white.columns-container .columns.awards > div img { + display: block; + height: 120px; + object-fit: contain; +} + +@media (min-width: 676px) and (max-width: 989px) { + .slide-left { + transform: translateX(-50%); + } +} + +@media (min-width: 990px) { + .columns.carousel button { + margin: -5px; + } + + .slide-left { + transform: translateX(-25%); + } + + .columns.with-box-shadow > div > div{ + border-bottom: none; + border-right: 2px solid var(--overlay-background-color); + min-height: 350px; + } + + .columns-container.video-left .columns-right-col { + width: 440px; + flex: none; + } +} + +.columns.carousel .active-button { + background-color: var(--link-color); +} + +.modal-container.get-bitdefender-familypack .columns.block.columns-2-cols > div { + display: flex; + flex-direction: column-reverse; + text-align: center; +} + +@media (min-width: 768px) { + .modal-container.get-bitdefender-familypack .columns.block.columns-2-cols > div { + display: flex; + flex: 1; + flex-direction: row; + order: unset; + justify-content: center; + align-items: center; + } +} + +.modal-container.modal-container.get-bitdefender-familypack .modal-content .section.columns-container { + border-bottom: none; + padding: 0; +} + +.columns-container[data-bg-image]{ + background-image: var(--bg-image-url); + background-size: cover; + background-position: center; + transition: padding-left 0.3s ease; + color: white; + text-align: center; + background-color: black; +} + +.linear-gradient.columns-container[data-bg-image]{ + background-size: cover; + background-position: center; + transition: padding-left 0.3s ease; + color: white; + background-image: none; + background-color: black; +} + +.columns.new-v2 h2 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 25px; + font-weight: 600; + line-height: 32px; + text-align: center; + margin: 1em auto; +} + +.columns-container.black-version.dlp h2{ + color: #e72325; +} + +@media (min-width: 768px) { + .linear-gradient.columns-container[data-bg-image]{ + background-image: linear-gradient(to right, rgb(39 1 107 / 100%) 20%, rgb(0 0 0 / 0%)), var(--bg-image-url); + } + + .columns-container[data-bg-image]{ + background-image: var(--bg-image-url); + } + + .linear-gradient.columns.bg-image > div { + width: calc(100% - 30%)!important; + } + + .columns.new-v2 h2 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 32px; + font-weight: 600; + line-height: 36px; + text-align: center; + width: 600px; + margin: 2em auto; + } + + .columns-container.black-version.dlp h2{ + color: #e72325; + } + + .columns.new-v2 h3 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 32px; + font-weight: 700; + line-height: 37px; + text-align: left; + color: #006EFF; + } + + .columns.new-v2 p { + font-size: 16px; + font-weight: 400; + line-height: 22px; + } + + .columns.new-v2 div.columns-text-col { + padding: 2em; + } + + .columns.new-v2 div.columns-right-col { + margin-left: 5em; + margin-right: 5em; + } + + .columns.new-v2 div.columns-left-col { + margin-left: 5em; + margin-right: 5em; + } +} + +@media (min-width: 1024px) { + .columns.new-v2 div.columns-left-col { + margin-right: 10em; + margin-left: 0; + } +} + +.columns.bg-image > div > div > h4 { + padding: 0 0 50px; + font-size: var(--heading-font-size-m); + font-style: bold; +} + +.columns.bg-image .button-container { + padding: 10px 0 0; +} + +.columns.bg-image svg { + filter: invert(1) grayscale(1) brightness(100); +} + +.columns.with-box-shadow { + box-shadow: 0 3px 8px 0 rgb(0 0 0 / 20%); + border-radius: 5px; + padding: 35px 0; + color: var(--checkbox-label); +} + +.columns.highlight-text.black.block > div > div:first-child { + font-size: var(--heading-font-size-l); +} + + +main .section.two-columns .right-col .products.plans a.button:any-link { + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); +} + +.two-columns .left-col p a.info-button.modal { + color: var(--white-color); + display: flex; + font-weight: var(--font-weight-regular); + align-items: baseline; +} + +.two-columns .left-col p a.info-button.modal:hover { + opacity: .8; +} + +.two-columns .left-col p a.info-button.modal::before { + content: url("/_src/icons/user-guide-white.svg"); + color: white; + padding-right: 8px; +} + +.columns.new-v2 a::after { + content: '\2192'; + width: 24px; + height: 24px; + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + margin-left: 2px; +} + +.columns.new-v2 a:hover::after { + transform: translateX(5px); +} + +.columns.carousel > div.carousel-buttons { + justify-content: center; +} + +.columns-container.icon-corners { + .columns-wrapper { + border-radius: 20px; + } + + .columns { + padding: 40px; + } + + > div { + position: relative; + } + + .columns > div { + align-items: center; + } + + > div > div > div:nth-child(1) > div:nth-child(2) { + flex: 2; + + h2 { + font-size: 32px; + text-align: center; + z-index: 1; + position: relative; + } + } + + span.icon-corner-left { + position: absolute; + top: 0; + left: 0; + width: 180px; + height: 180px; + z-index: 0; + } + + span.icon-corner-right { + position: absolute; + top: 0; + right: 0; + width: 180px; + height: 180px; + transform: rotateY(180deg); + z-index: 0; + } + + @media (min-width:768px){ + .columns > div { + align-items: baseline; + } + } +} + +@media (max-width: 1399px) { + .columns-wrapper { + padding: 0 var(--section-large-desktop-padding); + } + + /* stylelint-disable-next-line selector-class-pattern */ + .v2_benefits .columns-wrapper { + padding: var(--section-mobile-padding-vertical); + } + + .columns.video-presentation .button-container { + margin-right: 10px; + } + + .columns.screenshots > div { + justify-content: space-evenly; + } +} + +@media (max-width: 992px) { + .columns.carousel > div { + gap: 0; + } + + .creators .columns > div > div { + text-align: center; + } + + .columns.video-presentation > div > div { + width: 520px; + } + + .columns-wrapper > div.grey-bck > div > div { + flex: 1; + } + + .creators .header-mobile.columns-container div { + text-align: center; + } + + .creators .header-mobile h1 { + font-size: 32px; + line-height: 1.2; + } + + .creators .header-mobile h2 { + font-size: 16px; + line-height: 1.2; + color: #006DFF; + font-weight: bold; + margin-bottom: 0; + } + + .creators .header-mobile h3 { + font-size: var(--heading-font-size-l); + line-height: 1.2; + } + + .creators .columns-container h3, .creators .columns-container h5, .creators .columns-container h2, .creators .columns-container h1 { + font-family: "IBM Plex Sans", sans-serif; + } + + .creators .default-content-wrapper h2 { + font-family: "IBM Plex Sans", sans-serif; + } + + .creators .image-position.columns-container div.columns-img-col { + display: none; + } + + .creators .image-position.columns-container .columns > div > div { + text-align: center; + } + + .creators .no-space-top .default-content-wrapper h2 { + padding-top: 23px; + } + + .section.wide.light-sky-blue.columns-container.awards.v2 { + width: 100%; + padding: 0; + margin: 4em 0 2em; + } + + .columns-wrapper > div.grey-bck div.columns-text-col { + padding: 2em; + } +} + +@media (min-width: 768px) { + .v2 .columns > div { + flex-direction: row; + } + + .v2 .columns.awards .columns-wrapper { + padding: 0 10px 5em; + } + + .v2 .columns.awards > div > div > p:last-of-type { + max-width: 325px; + margin: 10px auto 0; + } + + .columns.screenshots > div { + flex-direction: row; + } + + .columns.screenshots > div > .columns-img-col { + flex: 0 0 230px; + } + + .columns-container.icon-corners { + .columns { + padding: 100px; + } + + span.icon-corner-left { + width: 400px; + height: 300px; + } + + span.icon-corner-right { + width: 400px; + height: 300px; + } + } +} + +@media (max-width: 767px) { + .columns-wrapper { + padding: var(--body-padding) var(--body-padding) 0; + } + + .cta .columns-img-col picture { + width: 345px; + } + + .columns.video-presentation > div > div > h3 { + font-size: var(--heading-font-size-l); + } + + .columns.carousel > div > div { + flex: 0 0 98%; + } +} + +@media (max-width: 500px) { + .columns.video-presentation > div > div { + width: 100%; + } + + .columns.carousel > div > div { + width: 100%; + flex: 1 0 100%; + box-sizing: border-box; + margin: 0; + } +} + +.columns-container.multi-blocks{ + max-width: 1330px; + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + display: flex; + flex-direction: column; + gap: 30px; + + .columns-wrapper { + padding: 0; + margin: 0; + } + + .columns{ + width: 100%; + background: #F6F6F6 0% 0% no-repeat padding-box; + border-radius: 20px; + opacity: 1; + padding: 20px; + } + + .columns > div > .columns-img-col img { + display: none; + } + + p{ + font-size: 16px; + margin: 0; + } + + .button-container{ + margin-top: 20px; + } + + .button-container a{ + width: 100%; + justify-content: center; + } + + &.grey-button{ + .button-container a{ + background-color: #0000; + border-color: #000; + color: #000 + } + } + + table{ + margin-bottom: 15px; + } + + td{ + display: flex; + gap:15px; + align-items: center; + + span{ + margin: 0; + } + + h3{ + font-size: 24px; + margin: 0; + } + + h6{ + font-size: 14px; + color: #5F5F5F; + line-height: 0; + } + + p{ + align-content: center; + } + + p:nth-last-of-type(2){ + margin: 0; + } + + hr{ + border: 1px solid #006EFF; + width: 25px; + line-height: 0; + } + } + + tr:last-of-type td{ + height: 25px; + } + + .columns > div > .columns-img-col { + margin-bottom: 0; + } + + @media (min-width: 991px) { + max-width: 1330px; + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + display: flex; + flex-direction: row; + gap: 30px; + + .columns{ + max-width: 630px; + } + + .columns > div > .columns-img-col img { + object-fit: cover; + display: block; + border-radius: 20px; + } + + .columns > div > .columns-text-col { + align-self: flex-start; + } + } + + @media (min-width: 1200px){ + .columns > div >div{ + width: 50%; + } + } +} diff --git a/_src/blocks/columns/columns.js b/_src/blocks/columns/columns.js new file mode 100644 index 000000000..1b5ebd37e --- /dev/null +++ b/_src/blocks/columns/columns.js @@ -0,0 +1,194 @@ +import { debounce, matchHeights } from '../../scripts/utils/utils.js'; + +function getItemsToShow() { + const width = window.innerWidth; + return width <= 767 ? 1 : 3; // 1 item for mobile, 2 for tablet, 3 for desktop +} + +function countSlides(carouselContent) { + return Math.ceil(carouselContent.children.length / getItemsToShow()); +} + +function showSlides(carousel, slideNumber) { + const carouselContent = carousel.querySelector('.columns.carousel > div:first-child'); + const itemsToShow = getItemsToShow(); + const translateXValue = -(carousel.clientWidth * slideNumber) / itemsToShow; + + carouselContent.style.transform = `translateX(${translateXValue}px)`; + carouselContent.style.transition = 'transform 0.5s ease'; +} + +function hideExcessElements(carousel) { + showSlides(carousel, 0); // Always show the first set initially +} + +function setActiveButton(button, buttonsWrapper) { + buttonsWrapper.querySelector('.active-button')?.classList.remove('active-button'); + button.classList.add('active-button'); +} + +function createNavigationButtons(numberOfSlides, carousel) { + const buttonsWrapper = document.createElement('div'); + buttonsWrapper.className = 'carousel-buttons'; + + Array.from({ length: numberOfSlides }, (_, i) => { + const button = document.createElement('button'); + button.setAttribute('aria-label', `Slide ${i + 1}`); + button.addEventListener('click', () => { + if (!button.classList.contains('active-button')) { + showSlides(carousel, i); + setActiveButton(button, buttonsWrapper); + } + }); + buttonsWrapper.appendChild(button); + return button; + }); + + buttonsWrapper.firstChild?.classList.add('active-button'); // Set first button as active + return buttonsWrapper; +} + +function setupCarousel(carousel, resetSlidePosition = false) { + const carouselContent = carousel.querySelector('.columns.carousel > div'); + if (resetSlidePosition) carouselContent.style.transform = 'translateX(0px)'; + + const buttonsWrapper = createNavigationButtons(countSlides(carouselContent), carousel); + carousel.querySelector('.carousel-buttons')?.remove(); // Remove existing buttons + carousel.appendChild(buttonsWrapper); + hideExcessElements(carousel); +} + +function setImageAsBackgroundImage() { + const columns = document.querySelectorAll('.columns.text-over-image > div > div'); + + columns.forEach((column) => { + const image = column.querySelector('img'); + + if (image) { + const src = image.getAttribute('src'); + + column.style.backgroundImage = `url(${src})`; + + // remove the p tag that contains the picture element + const pContainer = image.closest('p'); + if (pContainer) { + pContainer.remove(); + } + } + }); +} + +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const { linksOpenInNewTab, type } = block.closest('.section').dataset; + const cols = [...block.firstElementChild.children]; + block.classList.add(`columns-${cols.length}-cols`); + + // setup image columns + [...block.children].forEach((row) => { + [...row.children].forEach((col) => { + const pic = col.querySelector('picture'); + if (pic) { + const picWrapper = pic.closest('div'); + if (picWrapper && picWrapper.children.length === 1) { + // picture is only content in column + picWrapper.classList.add('columns-img-col'); + } + } else { + const children = [...row.children]; + + if (children.length === 1) { + col.closest('div').classList.add('columns-title-col'); + } else { + const firstParentIndex = children.indexOf(col.closest('div')); + + col.closest('div').classList.add('columns-text-col'); + if (firstParentIndex) { + col.closest('div').classList.add('columns-right-col'); + } else { + col.closest('div').classList.add('columns-left-col'); + } + } + } + }); + }); + + if (linksOpenInNewTab === 'true') { + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); + } + + if (block.classList.contains('text-over-image')) { + setImageAsBackgroundImage(); + } + + // If it has the carousel class, then setup the carousel + if (block.classList.contains('carousel')) { + setupCarousel(block); + } + + window.addEventListener('resize', debounce(() => { + // Check if the block still has the carousel class before resetting + if (block.classList.contains('carousel')) { + setupCarousel(block, true); // Pass true to reset the slide position + } + }, 250)); + window.dispatchEvent(new Event('resize')); // trigger resize to give width to columns + + const sectionDiv = document.querySelector('.columns-container[data-bg-image]'); + if (sectionDiv) { + const bgImageUrl = sectionDiv.getAttribute('data-bg-image'); + if (bgImageUrl) { + sectionDiv.style.setProperty('--bg-image-url', `url(${bgImageUrl})`); + } + } + + // This allows the event to cross the shadow DOM boundary + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, + }); + + if (type && type === 'video_left') { + block.closest('.section').classList.add('video-left'); + const leftCol = block.querySelector('.columns-img-col'); + const videoPath = leftCol.querySelector('tr:last-of-type').innerText.trim(); + const videoImg = leftCol.querySelector('img').getAttribute('src'); + + leftCol.innerHTML = ``; + } + + const chatOptions = document.querySelector('.chat-options'); + if (chatOptions) { + const cardButtons = chatOptions.querySelectorAll('.button-container'); + cardButtons.forEach((button) => { + button.previousElementSibling.classList.add('chat-options-text'); + }); + matchHeights(chatOptions, '.chat-options-text'); + matchHeights(chatOptions, 'table'); + } + block.querySelectorAll('h3')?.forEach((element) => { + if (element.textContent.includes('{GLOBAL_BIGGEST_DISCOUNT_PERCENTAGE}')) { + element.classList.add('await-loader'); + } + }); + matchHeights(block, 'h3'); + matchHeights(block, 'h4'); + if (block.closest('.section').classList.contains('multi-blocks')) { + matchHeights(block.closest('.section'), '.columns'); + matchHeights(block.closest('.section'), 'table'); + matchHeights(block.closest('.section'), 'p:nth-last-of-type(2)'); + matchHeights(block.closest('.section'), '.columns > div'); + } + if (block.classList.contains('awards-fragment')) { + matchHeights(block, 'p:last-of-type'); + } +} diff --git a/_src/blocks/creators-block/creators-block.css b/_src/blocks/creators-block/creators-block.css new file mode 100644 index 000000000..4286944c2 --- /dev/null +++ b/_src/blocks/creators-block/creators-block.css @@ -0,0 +1,184 @@ +@media (min-width: 992px) { + /* desktop */ + .creators-block-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +@media (min-width: 1600px) { + /* large desktop */ + .creators-block-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +.creators-block-wrapper { + border-radius: 20px; +} + +.creators-block.block>div { + position: relative; + padding-top: 40px; +} + +.creators-block.block>div:first-of-type img { + position: absolute; + right: 0; + top: 40px; +} + +.creators-block.block>div h3 { + text-align: left; + font-size: 60px; + line-height: 70px; + font-family: "IBM Plex Sans", sans-serif; + font-weight: normal; + letter-spacing: 0; + color: #FFF; +} + +.creators-block.block>div p { + text-align: left; + font-size: 28px; + line-height: 32px; + font-family: "IBM Plex Sans", sans-serif; + font-weight: bold; + letter-spacing: 0; + color: #FFF; +} + +.creators-block.block>div:nth-child(3) { + display: flex; + align-items: center; + justify-content: center; +} + +.creators-block.block>div:nth-child(3) a.button:any-link { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px / 24px Roboto, sans-serif; + margin-bottom: 35px; + color: white; +} + +.creators-block.block>div:nth-child(2)>div { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + grid-gap: 30px; +} + +.creators-block.block>div:nth-child(2) .creator-box { + display: flex; + position: relative; + width: 220px; + height: 310px; + padding: 16px 23px; + border-radius: 20px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(3) { + position: absolute; + color: #fff; + text-align: left; + font-size: 12px; + line-height: 16px; + font-family: Roboto, sans-serif; + font-weight: normal; + bottom: 16px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(2) { + position: absolute; + color: #016DFF; + text-align: left; + font-size: 12px; + line-height: 16px; + font-family: Roboto, sans-serif; + font-weight: normal; + bottom: 33px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(1) { + position: absolute; + color: #fff; + text-align: left; + font-size: 12px; + line-height: 16px; + font-family: Roboto, sans-serif; + font-weight: bold; + bottom: 64px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(1) img { + position: relative; + top: 10px; + width: 30px; +} + +@media (max-width: 1320px) { + .creators-block-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 8px; + } +} + +@media (max-width: 990px) { + .creators-block-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 8px; + } +} + +@media (max-width: 768px) { + .creators.creators-block-container .creators-block-wrapper { + margin: 0 8px; + } + + .creators.creators-block-container >div h3 { + font-size: var(--heading-font-size-l); + line-height: 1.2; + } + + .creators-block.block>div { + padding: 30px 0; + } + + .creators-block.block>div:first-of-type { + padding: 30px 0 0; + } + + .creators-block.block>div:last-of-type { + padding: 0; + } + + .creators-block.block>div p { + font-size: 22px; + line-height: 26px; + } + + .creators-block.block>div p:first-of-type { + margin: 0; + } + + .creators-block.block>div:first-of-type img { + position: relative; + width: 60px; + top: 0; + } +} + +@media (max-width: 525px) { + .creators-block.block>div:nth-child(2) .creator-box { + width: 100%; + height: 120vw; + } +} \ No newline at end of file diff --git a/_src/blocks/creators-block/creators-block.js b/_src/blocks/creators-block/creators-block.js new file mode 100644 index 000000000..23f8a405d --- /dev/null +++ b/_src/blocks/creators-block/creators-block.js @@ -0,0 +1,57 @@ +export default function decorate(block) { + const parentBlockStyle = block.closest('.section > div').style; + const { + // eslint-disable-next-line no-unused-vars + backgroundColor, + } = block.closest('.section').dataset; + + if (backgroundColor) parentBlockStyle.backgroundColor = backgroundColor; + + block.querySelectorAll('table').forEach((table) => { + const newDiv = document.createElement('div'); + newDiv.classList.add('creator-box'); + + const linkToCreator = table.querySelector('tr:nth-child(4) td'); + const creatorLink = linkToCreator ? linkToCreator.textContent.trim() : ''; + + // Find the image from the last row + const lastRow = table.querySelector('tr:last-child'); + const img = lastRow.querySelector('img'); + let backgroundImage = ''; + + if (img) { + backgroundImage = `url(${img.src})`; + } + + table.querySelectorAll('tr').forEach((tr, rowIndex) => { + // Skip the last row since we've already processed the image + if (rowIndex === table.rows.length - 1) return; + + tr.querySelectorAll('td').forEach((td) => { + const innerDiv = document.createElement('div'); + innerDiv.innerHTML = td.innerHTML; + newDiv.style.background = `linear-gradient(to bottom, rgba(0, 0, 0, 0) 60%, #000 100%), ${backgroundImage}`; + newDiv.style.backgroundSize = 'cover'; // Cover the whole div + newDiv.style.backgroundPosition = 'center'; // Center the image + newDiv.appendChild(innerDiv); + }); + }); + + // Remove the 4th div from creator-box + const fourthDiv = newDiv.querySelectorAll('div:nth-child(4)'); + if (fourthDiv.length > 0) { + newDiv.removeChild(fourthDiv[0]); + } + + // Wrap the newDiv in an anchor element if a link is found + if (creatorLink) { + const anchor = document.createElement('a'); + anchor.href = creatorLink; + anchor.target = '_blank'; + anchor.appendChild(newDiv); + table.parentNode.replaceChild(anchor, table); + } else { + table.parentNode.replaceChild(newDiv, table); + } + }); +} diff --git a/_src/blocks/dropdown-box/dropdown-box.css b/_src/blocks/dropdown-box/dropdown-box.css new file mode 100644 index 000000000..cbe2840b7 --- /dev/null +++ b/_src/blocks/dropdown-box/dropdown-box.css @@ -0,0 +1,620 @@ +.dropdown-box-container .block img { + width: 20px; +} + +.dropdown-box-container .block>div { + padding: 15px 30px; +} + +/* blue tbs */ +.dropdown-box-container .block>div>div { + border-bottom: 1px solid #D6D6D6; +} + +.dropdown-box-container .block>div:not(:first-child) { + padding: 0; + font-weight: 500; + display: flex; +} + +.dropdown-box-container .block>div:nth-child(1) { + color: #fff; + background-color: #006eff; + padding: 0; +} + +.dropdown-box-container .block>div:first-of-type>div, +.dropdown-box-container .block>div:last-of-type>div { + border-bottom: 0 none; +} + +.dropdown-box-container .block>div:nth-child(1)>div { + font-weight: bold; + cursor: pointer; + padding: 15px 30px; +} + +.dropdown-box-container .block>div:not(:first-child)>div { + flex: 1; + padding: 15px 2%; + display: inline-block; +} + +.dropdown-box-container .block>div>div strong em { + color: red; + font-style: normal; +} + +.dropdown-box-container .block.hide-title>div:nth-child(1)>div, +.dropdown-box-container.hide-title .block>div:nth-child(1)>div { + display: none; +} + +.dropdown-box-container .block:not(.selected-2)>div>div:nth-child(2), +.dropdown-box-container .block.selected-1>div>div:nth-child(2), +.dropdown-box-container .block.selected-2>div>div:nth-child(3), +.dropdown-box-container .block.selected-3>div>div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdown-box-container.selected-1 .block>div>div:nth-child(2), +.dropdown-box-container.selected-2 .block>div>div:nth-child(3), +.dropdown-box-container.selected-3 .block>div>div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdown-box-container.selected-2 .block>div>div:nth-child(2), +.dropdown-box-container.selected-3 .block>div>div:nth-child(2) { + background-color: white; +} + +.dropdown-box-container .block>div:not(:first-child)>div:first-child { + display: block; + align-items: center; +} + +.dropdown-box-container .block>div:not(:first-child)>div:first-child p { + margin: 0; +} + +.dropdown-box-container .block>div:not(:first-child)>div:first-child span { + margin-left: 10px; +} + +.dropdown-box-container .block.has2divs>div>div:nth-child(2) { + width: 66%; + background-color: white; +} + +.dropdown-box-container .block.inactive>div:not(:first-child)>div, +.dropdown-box-container .block.closed>div:not(:first-child)>div, +.dropdown-box-container.inactive .block>div:not(:first-child)>div, +.dropdown-box-container.closed .block>div:not(:first-child)>div { + display: none; +} + +.dropdown-box-container .block.baby-blue>div:not(:first-child)>div:first-child, +.dropdown-box-container.baby-blue .block>div:not(:first-child)>div:first-child { + background-color: #e3f2ff; +} + +.dropdown-box-container .block.closed.inactive>div:not(:first-child)>div, +.dropdown-box-container.closed .block.inactive>div:not(:first-child)>div { + display: inline-block; +} + +.dropdown-box-container .block.has2divs>div>div:nth-child(2) img { + width: 400px; +} + +.dropdown-box-container.awards90 .block.has2divs>div>div:nth-child(2) img { + width: 90%; +} + +.dropdown-box-container .block.inactive>div:nth-child(1)>div::before, +.dropdown-box-container .block.closed>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 10px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(-135deg); +} + +.dropdown-box-container.arrow-dark .block.inactive>div:nth-child(1)>div::before, +.dropdown-box-container.arrow-dark .block.closed>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 10px; + border: solid black; + border-width: 0 2px 2px 0; + transform: rotate(-135deg); +} + +/* handling - arrow down/up */ +/* stylelint-disable no-descending-specificity */ +.dropdown-box-container .block>div:nth-child(1)>div::before, +.dropdown-box-container .block.closed.inactive>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 4px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.dropdown-box-container.arrow-dark .block>div:nth-child(1)>div::before, +.dropdown-box-container.arrow-dark .block.closed.inactive>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 4px; + border: solid black; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.dropdown-box-container .default-content-wrapper h5 { + font-size: 40px; + line-height: 1.2; + font-weight: 500; + color: #000; + font-family: roboto, sans-serif; + margin-bottom: 22px; + text-align: left; +} + +.dropdown-box-container .new, +.dropdown-box-container.new .block { + padding: 0 0 2em 2em; + cursor: pointer; + box-shadow: 0 3px 8px 0 #E5E5E5; + position: relative; + border-radius: 10px; + margin-bottom: 1em; + z-index: 3; +} + +.dropdown-box-container .dropdown-box-wrapper { + position: relative; +} + +.dropdown-box-container>div:nth-child(2) .new::after, +.dropdown-box-container.new>div:nth-child(2) .block::after { + content: ""; + position: absolute; + top: -60px; + right: 0; + width: 196px; + height: 90pt; + background: url("../../images/patter_grid_blue.png") no-repeat; + z-index: -1; +} + +.dropdown-box-container .new div:nth-child(1), +.dropdown-box-container.new .block div:nth-child(1) { + background-color: white; + padding-top: 2em; + padding-right: 2em; +} + +.dropdown-box-container .new>div:not(:first-child), +.dropdown-box-container.new .block>div:not(:first-child) { + display: block; +} + +.dropdown-box-container .new.inactive>div:not(:first-child), +.dropdown-box-container.new .block.inactive>div:not(:first-child) { + display: none; +} + +.dropdown-box-container .new.closed>div:not(:first-child), +.dropdown-box-container.new.closed .block.inactive>div:not(:first-child) { + display: none; +} + +.dropdown-box-container .new.closed.inactive>div:not(:first-child), +.dropdown-box-container.new.closed .block>div:not(:first-child) { + display: block; +} + +.dropdown-box-container .new>div:nth-child(1)>div, +.dropdown-box-container.new .block>div:nth-child(1)>div { + background: transparent; + font-size: 24px; + line-height: 1.25; + font-weight: 600; + color: #000; + padding: 0; + position: relative; +} + +.dropdown-box-container .new>div:nth-child(1)>div::before, +.dropdown-box-container.new .block>div:nth-child(1)>div::before { + display: none; +} + +.dropdown-box-container .new>div:nth-child(1)>div::after, +.dropdown-box-container.new .block>div:nth-child(1)>div::after { + content: ""; + position: absolute; + display: block; + top: 0; + bottom: 0; + margin: auto 0; + right: 15px; + width: 10px; + height: 10px; + border: solid #c5c5c5; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + transition: top 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; +} + +.dropdown-box-container .new>div:not(:first-child)>div:first-child, +.dropdown-box-container.new .block>div:not(:first-child)>div:first-child { + padding: 0; + font-weight: 500; + display: block; + width: 100%; + font-size: 18px; + color: #3c3c3c; +} + +.dropdown-box-container .new>div:not(:first-child)>div:first-child a, +.dropdown-box-container.new .block>div:not(:first-child)>div:first-child a { + color: #006eff; +} + +.dropdown-box-container.slider .new>div:not(:first-child) p, +.dropdown-box-container.slider.new .block>div:not(:first-child) p { + text-align: center; +} + +.dropdown-box-container.slider .new>div:not(:first-child) p img, +.dropdown-box-container.slider.new .block>div:not(:first-child) p img { + width: 300px; +} + +.dropdown-box-container.dropdown-slider { + position: relative; + margin-bottom: 2em; +} + +.dropdown-box-container.dropdown-slider::after { + content: ""; + position: absolute; + top: 16px; + right: 0; + width: 196px; + height: 90pt; + background: url("../../images/patter_grid_blue.png") no-repeat; + z-index: 1; +} + +.dropdown-box-container.dropdown-slider .dropdown-box-wrapper { + display: none; +} + +.dropdown-box-container.dropdown-slider .slider-box { + position: initial; +} + +.dropdown-box-container.dropdown-slider .slider-box .title { + padding: 1em; + cursor: pointer; + box-shadow: 0 3px 8px 0 #E5E5E5; + position: relative; + border-radius: 10px; + margin-bottom: 1em; + z-index: 3; + font-size: 16px; + line-height: 1.25; + color: #000; +} + +.dropdown-box-container.dropdown-slider .slider-box .title::after { + content: ""; + position: absolute; + display: block; + top: 0; + bottom: 0; + margin: auto 0; + right: 15px; + width: 10px; + height: 10px; + border: solid #c5c5c5; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + transition: top 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; +} + +.dropdown-box-container.dropdown-slider.no-load-bar .slider-box .title { + cursor: default; +} + +.dropdown-box-container.dropdown-slider.no-load-bar .slider-box .title::after { + display: none; +} + +.dropdown-box-container.dropdown-slider .slider-box .title .loading-bar { + display: none; + position: absolute; + top: 0; + left: 0; + width: 0; + height: 4px; + background: #006eff; + font-size: 19px; + line-height: 22px; + margin-bottom: 1em; +} + +.dropdown-box-container.dropdown-slider .slider-box .description { + position: absolute; + right: 0; + padding-left: 5%; + display: none; + background-color: white; + z-index: 2; +} + +.dropdown-box-container.dropdown-slider .slider-box .active .title::after { + border-color: #006eff; + transform: rotate(225deg); + top: 11px; +} + +.dropdown-box-container.dropdown-slider .slider-box .active .title .loading-bar { + display: block; +} + +.dropdown-box-container.dropdown-slider .slider-box .active .description { + display: block; +} + +.dropdown-box-container { + clear: both; + padding: 0 var(--body-padding); + + .row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + + display: flex; + flex-wrap: wrap; + margin-top: calc(-1* var(--bs-gutter-y)); + margin-right: calc(-.5* var(--bs-gutter-x)); + } + + .row>* { + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x)* .5); + padding-left: calc(var(--bs-gutter-x)* .5); + margin-top: var(--bs-gutter-y); + } + + .col-12 { + flex: 0 0 auto; + width: 100%; + } + + @media (min-width: 768px) { + .col-md-7 { + flex: 0 0 auto; + width: 58.3333%; + } + } + + @media (min-width: 768px) { + .col-md-5 { + flex: 0 0 auto; + width: 41.6667%; + } + } + + &.container { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + + width: 100%; + padding-right: calc(var(--bs-gutter-x)* .5); + padding-left: calc(var(--bs-gutter-x)* .5); + margin-right: auto; + margin-left: auto; + + @media (min-width: 576px) { + max-width: 540px; + } + + @media (min-width: 768px) { + max-width: 720px; + } + + @media (min-width: 992px) { + max-width: 960px; + } + + @media (min-width: 1200px) { + max-width: 1140px; + } + + @media (min-width: 1400px) { + max-width: 1320px; + } + } + + @media (min-width: 990px) { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + @media (min-width: 1600px) { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + + +@media (width <=991px) { + .dropdown-box-container .default-content-wrapper h5 { + font-size: 33px; + } +} + +/* for mobile */ +@media (width <=768px) { + .dropdown-box-container { + clear: both; + padding: 0 15px 5px; + } + + .dropdown-box-container.dropdown-slider .dropdown-box-wrapper { + display: block; + } + + .dropdown-box-container.dropdown-slider .dropdown-box-wrapper img { + width: 90%; + } + + .dropdown-box-container.dropdown-slider .slider-box { + display: none; + } + + .dropdown-box-container .block>div:not(:first-child) { + display: block; + } + + .dropdown-box-container .block>div:nth-child(1)>div::before, + .dropdown-box-container .block.closed.inactive>div:nth-child(1)>div::before { + margin-top: 1px !important; + } + + .dropdown-box-container .block>div:nth-child(1)>div { + padding: 10px 3% !important; + display: flex; + font-size: 15px; + line-height: 17px; + } + + .dropdown-box-container .new>div:nth-child(1)>div::after, + .dropdown-box-container.new .block>div:nth-child(1)>div::after { + position: absolute; + right: -10px; + flex: 0 0 auto; + } + + .dropdown-box-container.no-dropdown-logic .block>div:nth-child(1)>div { + display: block; + } + + .dropdown-box-container.no-dropdown-logic .new>div:nth-child(1)>div::after, + .dropdown-box-container.no-dropdown-logic.new .block>div:nth-child(1)>div::after { + display: none; + } + + .dropdown-box-container>div:nth-child(2) .new::after { + top: -90px; + right: 0; + width: 135px; + height: 90pt; + display: none; + } + + .dropdown-box-container.dropdown-slider::after { + display: none; + } + + .dropdown-box-container .block>div:not(:first-child)>div { + padding: 8px 2% !important; + font-size: 15px; + } + + .dropdown-box-container .block img { + width: 15px; + } + + .dropdown-box-container .block>div:not(:first-child)>div:nth-child(1) { + width: 100%; + text-align: center; + } + + .dropdown-box-container .block>div:not(:first-child)>div:not(:first-child) { + width: 50%; + float: left; + } + + .dropdown-box-container .block.has4divs>div:not(:first-child)>div:not(:first-child) { + width: 33%; + min-height: 3em; + font-size: 13px; + line-height: 16px; + } + + .dropdown-box-container .block.has4divs>div:not(:first-child)>div:first-child p { + line-height: 17px; + } + + .dropdown-box-container .block.has3divs>div:not(:first-child)>div:not(:first-child) { + width: 50%; + min-height: 3em; + font-size: 13px; + line-height: 16px; + } + + .dropdown-box-container .block.has2divs>div:not(:first-child)>div:not(:first-child) { + width: 100%; + } + + .dropdown-box-container .default-content-wrapper h5 { + font-size: 30px; + line-height: 32px; + } + + .dropdown-box-container .new, + .dropdown-box-container.new .block { + padding: 15px; + } + + .dropdown-box-container .new p, + .dropdown-box-container.new .block p { + font-size: 15px; + } + + .dropdown-box-container .new div:nth-child(1), + .dropdown-box-container.new .block div:nth-child(1) { + padding-top: 0; + padding-right: 0; + } + + .dropdown-box-container .new div:nth-child(1)>div, + .dropdown-box-container.new .block div:nth-child(1)>div { + display: inline-block; + width: 95%; + font-size: 18px; + line-height: 24px; + } + + .dropdown-box-container .new ul, + .dropdown-box-container.new .block ul { + text-align: left; + } +} \ No newline at end of file diff --git a/_src/blocks/dropdown-box/dropdown-box.js b/_src/blocks/dropdown-box/dropdown-box.js new file mode 100644 index 000000000..468c09a25 --- /dev/null +++ b/_src/blocks/dropdown-box/dropdown-box.js @@ -0,0 +1,82 @@ +/* + Information: + - the tab is open by default + - [add-on] - will be treated as green tag + + Parameters: + - (closed) : for tab to be closed by default +*/ +export default function decorate(block) { + const parentSelector = block.closest('.section'); + const { type, topBackgroundColor, topTextColor } = parentSelector.dataset; + + // search for [] to replace with span greeenTag class + const getFirstDivs = block.querySelectorAll('.dropdown-box-container .block > div > div:nth-child(1)'); + getFirstDivs.forEach((item) => { + item.innerHTML = item.innerHTML.replace('[', ''); + item.innerHTML = item.innerHTML.replace(']', ''); + }); + + // make slideUp slideDown functionality + const getFirstTabs = block.querySelectorAll('.dropdown-box-container .block > div:first-child'); + getFirstTabs.forEach((tab) => { + tab.parentNode.classList.remove('inactive'); + tab.addEventListener('click', () => { + tab.parentNode.classList.toggle('inactive'); + }); + }); + + if (block.children.length >= 2) { + const childrenNr = block.children[1].children.length; + block.classList.add(`has${childrenNr}divs`); + + if (topBackgroundColor) { + block.querySelector('div:nth-child(1) > div > div').style.backgroundColor = topBackgroundColor; + } + + if (topTextColor) { + block.querySelector('div:nth-child(1) > div').style.color = topTextColor; + } + } + + // if it's slider + if (type === 'slider') { + block.closest('.dropdown-box-container').classList.add('container', 'dropdown-slider'); + const sliderBox = document.createElement('div'); + sliderBox.className = 'slider-box'; + + const infoTextEl = block.children[0].children[0]; + const infoTextEl2 = block.children[1].children[0]; + sliderBox.innerHTML = ` +
+
+
+ ${infoTextEl.innerHTML} +
+
${infoTextEl2.innerHTML}
+
+ `; + + block.closest('.dropdown-box-container').appendChild(sliderBox); + } + + // if it's slider + if (type === 'slider-no-load-bar') { + block.closest('.dropdown-box-container').classList.add('container', 'dropdown-slider', 'no-load-bar'); + const sliderBox = document.createElement('div'); + sliderBox.className = 'slider-box'; + + const infoTextEl = block.children[0].children[0]; + const infoTextEl2 = block.children[1].children[0]; + sliderBox.innerHTML = ` +
+
+ ${infoTextEl.innerHTML} +
+
${infoTextEl2.innerHTML}
+
+ `; + + block.closest('.dropdown-box-container').appendChild(sliderBox); + } +} diff --git a/_src/blocks/dropdownbox-compare/dropdownbox-compare.css b/_src/blocks/dropdownbox-compare/dropdownbox-compare.css new file mode 100644 index 000000000..d6ec62f61 --- /dev/null +++ b/_src/blocks/dropdownbox-compare/dropdownbox-compare.css @@ -0,0 +1,302 @@ +/* b-boxes .dropdownbox-compare-container */ +.dropdownbox-compare-container { + clear: both; + padding: 0!important; +} + +.dropdownbox-compare-container .block img { + width: 20px; +} + +.dropdownbox-compare-container .block > div { + padding: 0; + font-weight: 500; + display: flex; +} + +/* blue tbs */ +.dropdownbox-compare-container .block > div > div { + border-bottom: 1px solid #e4f2ff; + border: 1px solid #e4f2ff; + flex: 1; + padding: 15px 20px; + display: inline-block; +} + +.dropdownbox-compare-container .block > div:nth-child(1) > div { + font-weight: bold; + cursor: pointer; +} + +.dropdownbox-compare-container .block > div > div strong em { + color: red; + font-style: normal; +} + +.dropdownbox-compare-container .block > div:first-of-type > div, .dropdownbox-compare-container .block > div:last-of-type > div { + border-bottom: 0 none; +} + +.dropdownbox-compare-container .block > div > div:not(:nth-child(1)) { + display: flex; + align-items: center; + justify-content: center; +} + +.dropdownbox-compare-container .block > div:nth-child(1) > div:nth-child(1) { + color: #fff; + background-color: #006eff; +} + +.dropdownbox-compare-container .block > div:not(:nth-child(1)) > div:nth-child(1) { + background: #e4f2ff; +} + +.dropdownbox-compare-container .block:not(.selected-2) > div > div:nth-child(2), .dropdownbox-compare-container .block.selected-1 > div > div:nth-child(2), .dropdownbox-compare-container .block.selected-2 > div > div:nth-child(3), .dropdownbox-compare-container .block.selected-3 > div > div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdownbox-compare-container.selected-1 .block > div > div:nth-child(2), .dropdownbox-compare-container.selected-2 .block > div > div:nth-child(3), .dropdownbox-compare-container.selected-3 .block > div > div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdownbox-compare-container.selected-2 .block > div > div:nth-child(2), .dropdownbox-compare-container.selected-3 .block > div > div:nth-child(2) { + background-color: white; +} + +.dropdownbox-compare-container .block > div:not(:first-child) > div:first-child { + display: block; + align-items: center; +} + +.dropdownbox-compare-container .block > div > div p { + font-family: roboto, sans-serif; + font-size: 14px; + font-weight: 400; +} + +.dropdownbox-compare-container .block > div:first-child > div p { + color: white; +} + +.dropdownbox-compare-container .block > div:not(:first-child) > div p { + color: #616161; +} + +.dropdownbox-compare-container .block > div > div:first-child p { + margin: 0; + margin-left: 26px; +} + +.dropdownbox-compare-container .block > div > div span.green-tag { + background: #2cb43d; + border-radius: 50px; + color: #3c3c3c; + color: #fff !important; + display: block; + font-family: roboto, sans-serif; + font-size: 10px !important; + font-style: normal; + font-weight: 700; + margin: -5px 0 6px; + padding: 0 20px; + padding: 3px 9px !important; + text-transform: uppercase; + width: fit-content; +} + + +.dropdownbox-compare-container .block > div > div strong { + font-size: 14px; + line-height: 1.5; + font-weight: normal; +} + +.dropdownbox-compare-container .block.closed > div:not(:first-child) > div, .dropdownbox-compare-container.closed .block > div:not(:first-child) > div { + display: none; +} + +.dropdownbox-compare-container .block.closed > div > div:not(:nth-child(1)) { + display: flex; + align-items: center; + justify-content: center; +} + +.dropdownbox-compare-container .block.closed > div:not(:first-child) > div:first-of-type, .dropdownbox-compare-container.closed .block.closed > div:not(:first-child) > div:first-of-type { + display: inline-block; +} + +.dropdownbox-compare-container .block.closed > div:nth-child(1) > div:nth-child(1)::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 10px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(-135deg); +} + +/* handling - arrow down/up */ +/* stylelint-disable no-descending-specificity */ +.dropdownbox-compare-container.no-arrow .block > div:nth-child(1) > div::before { + visibility: hidden; +} + +.dropdownbox-compare-container .block > div:nth-child(1) > div::before, +.dropdownbox-compare-container .block.closed > div:nth-child(1) > div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 4px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.dropdownbox-compare-container .dropdownbox-compare-wrapper { + position: relative; +} + +@media (width <= 991px) { + .dropdownbox-compare-container .default-content-wrapper h5 { + font-size: 33px; + } +} + +/* for mobile */ +@media (width <= 991px) { + .dropdownbox-compare-container .block > div { + display: block; + } + + .dropdownbox-compare-container .block > div > div:nth-child(1) { + width: 100%; + } + + .dropdownbox-compare-container .block > div > div:not(:nth-child(1)) { + width: 33%!important; + float: left; + } +} + +@media (width <= 768px) { + .dropdownbox-compare-container { + clear: both; + padding: 0 15px 5px; + } + + .dropdownbox-compare-container .block > div:not(:first-child) { + display: block; + } + + .dropdownbox-compare-container .block > div:nth-child(1) > div:nth-child(1)::before, .dropdownbox-compare-container .block.closed.close > div:nth-child(1) > div:nth-child(1)::before { + margin-top: 1px !important; + } + + .dropdownbox-compare-container .block > div:nth-child(1) > div { + padding: 10px 3% !important; + display: flex; + font-size: 15px; + line-height: 17px; + } + + .dropdownbox-compare-container .new > div:nth-child(1) > div:nth-child(1)::after, .dropdownbox-compare-container.new .block > div:nth-child(1) > div:nth-child(1)::after { + position: static; + margin-left: 15px; + flex: 0 0 auto; + } + + .dropdownbox-compare-container > div:nth-child(2) .new::after { + top: -90px; + right: 0; + width: 135px; + height: 90pt; + display: none; + } + + .dropdownbox-compare-container .block > div:not(:first-child) > div { + padding: 8px 2% !important; + font-size: 15px; + } + + .dropdownbox-compare-container .block img { + width: 15px; + } + + .dropdownbox-compare-container .block > div:not(:first-child) > div:nth-child(1) { + width: 100%; + text-align: center; + } + + .dropdownbox-compare-container .block > div:not(:first-child) > div:not(:first-child) { + width: 50%; + float: left; + } + + .dropdownbox-compare-container .default-content-wrapper h5 { + font-size: 30px; + line-height: 32px; + } + + .section.product-comparison-table-container.migration .old-price-box { + flex-direction: column; + } + + .section.product-comparison-table-container.migration .old-price-box span { + flex-direction: column; + justify-content: center; + align-items: center; + margin: 5px 0; + } + + .section.product-comparison-table-container.migration .old-price-box span del { + margin-left: 10px; + } + + .section.product-comparison-table-container.migration .new-price-box { + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 22px; + } + + .section.product-comparison-table-container.migration .new-price-box span { + margin: 0 0 7px; + } + + .section.product-comparison-table-container.migration .product-comparison-price > p:last-of-type, .section.product-comparison-table-container.migration .product-comparison-header div[role="columnheader"] p { + text-align: center; + min-height: auto; + } + + .section.product-comparison-table-container.migration h3 { + font-size: 15px !important; + } + + .section.product-comparison-table-container.migration p.button-container { + margin-bottom: 1em; + } + + .section.product-comparison-table-container.migration .product-comparison-price { + margin: 3px; + } +} + +@media (min-width: 992px) { + .dropdownbox-compare-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + } +} + +@media (min-width: 580px) { + .dropdownbox-compare-wrapper { + margin: 0 auto; + overflow-y: visible; + + } +} diff --git a/_src/blocks/dropdownbox-compare/dropdownbox-compare.js b/_src/blocks/dropdownbox-compare/dropdownbox-compare.js new file mode 100644 index 000000000..4566f113d --- /dev/null +++ b/_src/blocks/dropdownbox-compare/dropdownbox-compare.js @@ -0,0 +1,17 @@ +export default function decorate(block) { + // search for [] to replace with span greeenTag class + const getFirstDivs = block.querySelectorAll('.dropdownbox-compare-container .block > div > div:nth-child(1)'); + getFirstDivs.forEach((item) => { + item.innerHTML = item.innerHTML.replace('[', ''); + item.innerHTML = item.innerHTML.replace(']', ''); + }); + + // make slideUp slideDown functionality + const getFirstTabs = block.querySelectorAll('.dropdownbox-compare-container .block > div:first-child'); + getFirstTabs.forEach((tab) => { + tab.parentNode.classList.remove('closed'); + tab.addEventListener('click', () => { + tab.parentNode.classList.toggle('closed'); + }); + }); +} diff --git a/_src/blocks/dual-teaser/dual-teaser.css b/_src/blocks/dual-teaser/dual-teaser.css new file mode 100644 index 000000000..6825ab5c7 --- /dev/null +++ b/_src/blocks/dual-teaser/dual-teaser.css @@ -0,0 +1,148 @@ +/* stylelint-disable no-descending-specificity */ +.dual-teaser-container.section { + background: transparent linear-gradient(180deg, #006EFF 0%, #000 100%) 0 0 no-repeat padding-box; + overflow: unset; + padding-top: 0; +} + +.dual-teaser-container.section::before { + content: ''; + display: block; + width: 100%; + height: 200px; + background: #EFF6FF; + position: relative; + top: -1px; +} + +.dual-teaser-container .col-container { + width: 100%; +} + +.dual-teaser-container .col-container:first-child { + margin-bottom: 20px; +} + +.dual-teaser-container .col-container .card { + width: 100%; + height: 350px; + position: relative; + display: flex; + flex-direction: column; + justify-content: flex-end; + border-radius: 10px; + overflow: hidden; +} + +.dual-teaser-container .default-content-wrapper { + margin-top: -120px; +} + +.dual-teaser-container .img-container { + width: 100%; + height: 100%; + position: absolute; + overflow: hidden; + border-radius: inherit; +} + +.dual-teaser-container .col-container .box { + height: 190px; + padding: 10px; + background: #003b89a3 0 0 no-repeat padding-box; + backdrop-filter: blur(30px); + display: flex; + flex-direction: column; + border-bottom-right-radius: 10px; + border-bottom-left-radius: 10px; +} + +.dual-teaser-container .col-container .box h2, +.dual-teaser-container .col-container .box h3, +.dual-teaser-container .col-container .box h4, +.dual-teaser-container .col-container .box h5 { + color: white; + letter-spacing: 0; +} + +.dual-teaser-container .col-container .box p, +.dual-teaser-container .col-container .box div { + font: normal normal normal 14px/18px "IBM Plex Sans", sans-serif; + letter-spacing: 0; + margin: 0; +} + +.dual-teaser-container .col-container .box .button-container { + margin-top: auto; +} + +.dual-teaser-container .col-container .box a { + width: 100%; + justify-content: center; +} + +.dual-teaser-container .col-container span.icon { + display: none; +} + +@media (min-width: 768px) { + .dual-teaser-container .default-content-wrapper { + width: 100%; + display: flex; + margin-top: -180px; + } + + .dual-teaser-container .col-container:first-child { + margin-top: unset; + } + + .dual-teaser-container .col-container:first-child .card { + border-radius: 20px 0 0 20px; + } + + .dual-teaser-container .col-container:last-child .card { + border-radius: 0 20px 20px 0; + } + + .dual-teaser-container .col-container { + position: relative; + margin-bottom: 0; + } + + .dual-teaser-container .col-container .card { + height: 600px; + } + + .dual-teaser-container .col-container .box { + padding: 33px 7% 33px 33px; + height: 270px; + border-bottom-right-radius: unset; + border-bottom-left-radius: unset; + } + + .dual-teaser-container .col-container .box a { + width: unset; + } + + .dual-teaser-container .col-container .box p, + .dual-teaser-container .col-container .box div { + font: normal normal normal 18px/23px "IBM Plex Sans", sans-serif; + letter-spacing: 0; + } + + .dual-teaser-container .col-container .box h2, + .dual-teaser-container .col-container .box h3, + .dual-teaser-container .col-container .box h4, + .dual-teaser-container .col-container .box h5 { + margin-bottom: 16px; + } + + .dual-teaser-container .col-container span.icon { + display: block; + position: absolute; + width: 90px; + height: 90px; + top: 20%; + left: -45px; + } +} diff --git a/_src/blocks/dual-teaser/dual-teaser.js b/_src/blocks/dual-teaser/dual-teaser.js new file mode 100644 index 000000000..ea070b10a --- /dev/null +++ b/_src/blocks/dual-teaser/dual-teaser.js @@ -0,0 +1,34 @@ +import { decorateIcons } from '../../scripts/lib-franklin.js'; + +export default async function decorate(block) { + const cols = [...block.children[1].children]; + const middleSvgIcon = block.children[0].querySelector('span'); + + block.innerHTML = ` +
+ ${cols.map((col, idx) => { + const pictureEl = col.querySelector('picture'); + const richTextEls = [...col.children]; + richTextEls.shift(); + const [titleEl, subtitleEl, buttonEl] = richTextEls; + + return ` +
+
+
+ ${pictureEl.outerHTML} +
+
+ ${titleEl.outerHTML} +
${subtitleEl.innerHTML}
+ ${buttonEl.outerHTML} +
+
+ ${idx === 1 ? middleSvgIcon.outerHTML : ''} +
+ `; + }).join('')} + `; + + decorateIcons(block); +} diff --git a/solutions/blocks/embed/embed.css b/_src/blocks/embed/embed.css similarity index 89% rename from solutions/blocks/embed/embed.css rename to _src/blocks/embed/embed.css index dde6988ff..18949cb11 100644 --- a/solutions/blocks/embed/embed.css +++ b/_src/blocks/embed/embed.css @@ -65,3 +65,12 @@ main .embed .embed-placeholder-play button::before { top: 0.25rem; left: 0.4375rem; } + +main .ferrari.embed-container .embed{ + max-width: 1332px; + padding: 0 20px; +} + +main .ferrari.embed-container .embed iframe{ + border-radius: 10px; +} \ No newline at end of file diff --git a/solutions/blocks/embed/embed.js b/_src/blocks/embed/embed.js similarity index 100% rename from solutions/blocks/embed/embed.js rename to _src/blocks/embed/embed.js diff --git a/_src/blocks/exit-popup/exit-popup.css b/_src/blocks/exit-popup/exit-popup.css new file mode 100644 index 000000000..d5eb54807 --- /dev/null +++ b/_src/blocks/exit-popup/exit-popup.css @@ -0,0 +1,96 @@ +/* stylelint-disable no-descending-specificity */ +main .exit-popup-container { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgb(0 0 0 / 70%); + z-index: 9999; + display: none; +} + +main .exit-popup-wrapper { + width: 460px; + position: fixed; + z-index: 999; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border-radius: 10px; + background-color: white; + color: black; + padding: 0; + box-shadow: 0 3px 6px #00000029; + overflow: hidden; +} + +main .exit-popup-container #exit-action { + position: absolute; + top: 1em; + right: 1em; + width: 15px; + height: 15px; + cursor: pointer; +} + +main .exit-popup-container #exit-action:hover { + opacity: 0.6; +} + +main .exit-popup-container .block p { + margin: 5px 0; +} + +main .exit-popup-container .block > div { + padding: 1em; +} + +main .exit-popup-container .block > div:first-of-type { + background: #006DFF; + color: white; +} + +main .exit-popup-container .block > div:first-of-type p { + margin-top: 0; + font-family: roboto, sans-serif; + font-size: 24px; + line-height: 32px; + font-weight: 400; +} + +main .exit-popup-container .block > div:first-of-type h5 { + font-family: roboto, sans-serif; + font-size: 32px; + line-height: 35px; + font-weight: 500; +} + +main .exit-popup-container .block > div:last-of-type a:last-of-type { + width: 100%; + text-align: center; + display: flex; + align-items: center; + justify-content: center; + font-family: roboto, sans-serif; + font-size: 18px; + line-height: 24px; + font-weight: 500; + margin: 1em auto; +} + +main .exit-popup-container .block > div:last-of-type a:last-of-type:hover::after { + margin-left: 0; +} + +main .exit-popup-container .block > div:last-of-type p strong { + font-family: roboto, sans-serif; + font-size: 24px; + line-height: 32px; +} + +@media (max-width: 460px) { + main .exit-popup-container { + width: 90%; + } +} \ No newline at end of file diff --git a/_src/blocks/exit-popup/exit-popup.js b/_src/blocks/exit-popup/exit-popup.js new file mode 100644 index 000000000..450a1755b --- /dev/null +++ b/_src/blocks/exit-popup/exit-popup.js @@ -0,0 +1,87 @@ +import { ProductInfo, Store } from '../../scripts/libs/store/store.js'; +// eslint-disable-next-line no-unused-vars +export default async function decorate(block) { + const parentSelector = block.closest('.section'); + const { product, custompid } = parentSelector.dataset; + + if (product) { + const [alias, devices, years] = product.split(','); + // eslint-disable-next-line no-undef + const products = await Store.getProducts([new ProductInfo(alias, 'consumer', custompid)]); + const productItem = products[alias]; + const productCurrency = productItem.currency; + const productRegionId = productItem.regionId; + const variation = productItem.getOption(Number(devices), Number(years)); + const percentPrice = variation.getDiscount('percentage'); + const newPrice = variation.priceDiscounted; + const oldPrice = variation.price; + + // discount in the title + const tileDiscountEl = block.querySelector('h5'); + if (tileDiscountEl) tileDiscountEl.innerHTML = tileDiscountEl.innerHTML.replace('50%', `${percentPrice}%`); + + // buy button + const buyBtnEl = block.querySelector('p.button-container a'); + if (buyBtnEl) { + buyBtnEl.textContent = buyBtnEl.textContent.replace('50%', `${percentPrice}%`); + buyBtnEl.setAttribute('href', await variation.getStoreUrl()); + buyBtnEl.setAttribute('data-product', alias); + buyBtnEl.setAttribute('data-buy-price', newPrice); + buyBtnEl.setAttribute('data-old-price', oldPrice); + buyBtnEl.setAttribute('data-currency', productCurrency); + buyBtnEl.setAttribute('data-region', productRegionId); + buyBtnEl.setAttribute('data-variation', `${devices}u-${years}y`); + } + } + + // exit element: x + const exitEl = document.createElement('span'); + exitEl.id = 'exit-action'; + exitEl.innerHTML = 'Bitdefender'; + block.appendChild(exitEl); + + // popup configuration: + const POPUP_DISPLAY_LIMIT = 2; + const POPUP_TIMEOUT_DAYS = 30; + let popupDisplayCount = parseInt(localStorage.getItem('popupDisplayCount') || 0, 10); + const lastPopupDate = parseInt(localStorage.getItem('lastPopupDate') || 0, 10); + + // if 30 days have passed + function hasThirtyDaysPassed(lastDisplayDate) { + const thirtyDaysInMs = POPUP_TIMEOUT_DAYS * 24 * 60 * 60 * 1000; + const now = Date.now(); + return now - lastDisplayDate > thirtyDaysInMs; + } + + // reset count if 30 days have passed + if (lastPopupDate && hasThirtyDaysPassed(lastPopupDate)) { + localStorage.removeItem('popupDisplayCount'); + localStorage.removeItem('lastPopupDate'); + popupDisplayCount = 0; // Reset count for the session + } + + // event: mouseout -> display the popup + document.addEventListener('mouseout', (event) => { + if (popupDisplayCount < POPUP_DISPLAY_LIMIT && event.clientY < 0 && parentSelector) { + parentSelector.style.display = 'block'; + document.dispatchEvent(new Event('exit_popup_display')); + window.exit_popup_display = true; + + // add to the count + popupDisplayCount += 1; + localStorage.setItem('popupDisplayCount', popupDisplayCount.toString()); + + // last display time + localStorage.setItem('lastPopupDate', Date.now().toString()); + } + }); + + // Close the popup: x-icon + background + const closePopup = () => { + const popup = document.querySelector('main .exit-popup-container'); + if (popup) popup.style.display = 'none'; + }; + + if (exitEl) exitEl.addEventListener('click', closePopup); + parentSelector.addEventListener('click', closePopup); +} diff --git a/solutions/blocks/features/features.css b/_src/blocks/features/features.css similarity index 88% rename from solutions/blocks/features/features.css rename to _src/blocks/features/features.css index 065dc557c..af7d37b1d 100644 --- a/solutions/blocks/features/features.css +++ b/_src/blocks/features/features.css @@ -11,7 +11,7 @@ .features { box-shadow: 0 3px 8px 0 var(--dark-shadow); border-radius: 8px; - padding: 40px 15px 20px; + padding: 3em 1em; } .features > div { @@ -21,7 +21,7 @@ } .features img { - width: 100%; + width: 56px; } .features > div > div { @@ -59,8 +59,18 @@ line-height: 1.5; } -.features p.features-tabs-hidden { - display: none; +.features p:nth-of-type(2) { + margin-top: 5px; +} + +.features > div > div > p:first-of-type { + height: 55px; +} + +.features h3 { + font-size: var(--heading-font-size-m); + font-weight: var(--font-weight-bold); + margin-bottom: 0; } .features ul { @@ -90,8 +100,8 @@ width: 14px; height: 8px; margin: 0 3px; - background: url("/solutions/icons/tabs_arrow.svg") no-repeat; - background-size: 100%;; + background: url("/_src/icons/tabs_arrow.svg") no-repeat; + background-size: 100%; transform: rotate(180deg); transition: all .3s linear; } @@ -191,5 +201,12 @@ .features-wrapper { max-width: var(--section-large-desktop-max-width); padding: 0 var(--section-large-desktop-padding); + margin-top: 3em; } } + +@media (max-width: 500px) { /* mobile */ + .features { + padding: 1em; + } +} \ No newline at end of file diff --git a/solutions/blocks/features/features.js b/_src/blocks/features/features.js similarity index 92% rename from solutions/blocks/features/features.js rename to _src/blocks/features/features.js index 3f31f678c..94d60841c 100644 --- a/solutions/blocks/features/features.js +++ b/_src/blocks/features/features.js @@ -1,3 +1,5 @@ +import { matchHeights } from '../../scripts/utils/utils.js'; + function expandItem(content) { content.style.height = `${content.scrollHeight}px`; const transitionEndCallback = () => { @@ -134,4 +136,13 @@ export default function decorate(block) { col.appendChild(extractFeatures(col)); }); }); + + const featuresList = block.querySelectorAll('ul'); + if (featuresList) { + featuresList.forEach((list) => { + const featureText = list.previousElementSibling; + featureText.classList.add('feature-text'); + }); + } + matchHeights(block, '.feature-text'); } diff --git a/_src/blocks/footer/footer.css b/_src/blocks/footer/footer.css new file mode 100644 index 000000000..402b2f809 --- /dev/null +++ b/_src/blocks/footer/footer.css @@ -0,0 +1,768 @@ +footer.landingpage { + background: #006EFF; + color: white; + font-weight: 400; + +a:any-link { + color: white; + text-decoration: none; +} + +img { + width: 300px; + height: auto; + margin-bottom: 10px; +} +} + +footer.default { + padding: 2.5rem 0 1.5rem; + background-color: #000; + font-size: var(--body-font-size-s); +} + +footer.default .footer a { + color: #fff; + cursor: pointer; + outline: 0; + font-family: var(--body-font-family),sans-serif; +} + +footer.default .footer ul { + list-style: none; + padding: 0 1.25rem; + margin: 0; + font-family: var(--body-font-family), sans-serif; +} + +footer.default .footer ul li { + font-size: var(--body-font-size-s); + line-height: 1.63; + font-family: var(--body-font-family),sans-serif; + margin: 0 0 0.4375rem; + padding-left: 0; +} + +footer.default .footer ul li a { + font: normal normal var(--font-weight-boldest) 10px/30px var(--body-font-family); +} + +footer.default .footer p { + margin: 0; + padding: 0 1.25rem; +} + +footer.default .footer .deactivated a { + color: #999 !important; + cursor: auto; + pointer-events: none; +} + +footer.default .footer a:hover { + text-decoration: underline; +} + +footer.default .footer .deactivated::before { + content: "•"; + color: #999; + font-weight: var(--font-weight-boldest); + display: inline-block; + width: 1rem; + position: absolute; + z-index: 1; + left: -1rem; + top: 0.125rem; +} + +footer.default .footer > div { + display: grid; + margin: 0 auto; + max-width: 81.25rem; +} + +footer.default .footer > div div { + margin: 0; + padding: 0; + border-bottom: 0.0625rem solid #9098a3; +} + +footer.default .footer > div p { + text-align: left; + font: normal normal var(--font-weight-boldest) 13px/24px var(--body-font-family); + letter-spacing: 0; + color: #9098a3; + opacity: 1; + position: relative; + margin: 0; + transition: transform .5s ease-in-out; + cursor: pointer; + padding: 0.625rem 1.25rem; +} + +footer.default .footer > div > :nth-child(1) > p { + width: 100%; + margin-bottom: 1.875rem; + display: flex; + overflow: hidden; + border: none; +} + +footer.default .footer > div > :nth-child(1) > p a { + height: 100%; +} + +footer.default .footer > div > :nth-child(1) > p picture { + width: 11.875rem; + height: 1.9375rem; + overflow: hidden; + display: flex; +} + +footer.default .footer > div > :nth-child(1) > p a img { + height: 1.5rem; + width: auto; + object-fit: contain; +} + +footer.default .footer > div > :nth-child(1) > ul { + margin: 0; + display: block; + column-count: 2; + list-style-type: none; + padding-bottom: 1.875rem; +} + +footer.default .footer > div > :nth-child(1) > ul li { + padding: 0; + margin: 0 0 0.4375rem; +} + +footer.default .footer > div > :nth-child(1) > ul li a { + text-align: left; + letter-spacing: .78pt; + text-transform: uppercase; + font: normal normal var(--font-weight-boldest) 11px/30px var(--body-font-family); +} + +footer.default .footer > div > :nth-child(2) { + order: 4; + margin-top: 0.6875rem; + margin-bottom: 1.5rem; + border: none; +} + +footer.default .footer > div > :nth-child(3) { + order: 2; + padding-bottom: 0.625rem; +} + +footer.default .footer > div > :nth-child(4) { + order: 3; + padding-bottom: 0.625rem; +} + +footer.default .footer > div > :nth-child(5) { + order: 5; + padding: 0; + border-bottom-width: 1px; + border-style: solid; + border-color: rgb(144 152 163); + margin-bottom: 1.5rem; +} + +footer.default .footer > div > :nth-child(6) { + order: 6; + border: none; +} + +footer.default .footer > div > :nth-child(3) > p::before, +footer.default .footer > div > :nth-child(4) > p::before { + transform: rotate(45deg); + border-color: #fff; + border-style: solid; + border-width: 0 0.1875rem 0.1875rem 0; + content: ""; + width: 0.5rem; + height: 0.5rem; + display: inline-block; + position: absolute; + right: 1.25rem; + top: 0.75rem; + left: auto; + transition: transform .5s ease-in-out; +} + +footer.default .footer > div > :nth-child(3) > ul, +footer.default .footer > div > :nth-child(4) > ul { + width: 100%; + max-height: 125rem; + margin-bottom: 0.625rem; + transition: transform .5s ease-in-out; +} + +footer.default .footer > div > :nth-child(3) > ul li, +footer.default .footer > div > :nth-child(4) > ul li { + margin: 0 0 0.625rem; + padding-left: 0; +} + +footer.default .footer > div > :nth-child(3) > ul li > a, +footer.default .footer > div > :nth-child(4) > ul li > a { + font: normal normal var(--font-weight-bold) 10px/30px var(--body-font-family); + letter-spacing: 0; + opacity: 1; +} + +footer.default .footer > div > :nth-child(2) > ul { + column-count: 2; + padding: 0 1.25rem 0.375rem; + margin-top: 0.6875rem; +} + +footer.default .footer > div > :nth-child(3) > p + ul, +footer.default .footer > div > :nth-child(4) > p + ul { + display: none; + max-height: 0; + overflow: hidden; + transition: max-height 0.5s ease-in-out; +} + +footer.default .footer > div > :nth-child(3) > p + ul.visible, +footer.default .footer > div > :nth-child(4) > p + ul.visible { + display: block; +} + +footer.default .footer > div > :nth-child(3) > p + ul.open, +footer.default .footer > div > :nth-child(4) > p + ul.open { + max-height: 400px; +} + +footer.default .footer > div > :nth-child(3) > p, +footer.default .footer > div > :nth-child(4) > p { + padding-bottom: 0; +} + +footer.default .footer > div > :nth-child(3) > p.active, +footer.default .footer > div > :nth-child(4) > p.active { + padding-bottom: 0.625rem; +} + +footer.default .footer > div > :nth-child(4) > p + ul { + display: none; +} + +footer.default .footer > div > :nth-child(3) > p.active + ul, +footer.default .footer > div > :nth-child(4) > p.active + ul { + display: inline-block; +} + +footer.default .footer > div > :nth-child(4) > p.active + ul { + column-count: 2; +} + +footer.default .footer > div > :nth-child(3) > p.active::before, +footer.default .footer > div > :nth-child(4) > p.active::before { + transform: rotate(225deg); + top: 1.0625rem; +} + +footer.default .footer > div > :nth-child(2) > p { + padding: 0 1.25rem; + margin-bottom: 1rem; +} + +footer.default .footer > div > :nth-child(5) > p { + font-size: var(--body-font-size-m); + padding: 0 1.375rem 1.5rem; + color: rgb(255 255 255); + letter-spacing: 0; + line-height: 1.5rem; + font-weight: var(--font-weight-boldest); + font-family: "IBM Plex Sans" ,sans-serif; +} + +footer.default .footer > div > :nth-child(6) > p { + font: normal normal normal 10px/13px var(--body-font-family); + width: 100%; + max-width: 100%; + margin-top: 1rem; + margin-bottom: 1.625rem; + position: relative; + text-align: left!important; + letter-spacing: 0; + color: #9098a3; + opacity: 1; + line-height: 1.14!important; + padding: 0 1.25rem; +} + +footer.default .footer > div > :nth-child(6) > ul li { + display: block; + margin-bottom: 0.625rem; + font: normal normal var(--font-weight-regular) 10px/30px var(--body-font-family); + width: 100%; + line-height: 1; + font-size: var(--body-font-size-xxs); +} + +footer.default .footer > div > :nth-child(6) > ul li > a { + display: inline-block; + font: normal normal var(--font-weight-bold) 10px/30px var(--body-font-family); +} + +@media(min-width: 480px) { + footer.default .footer > div > :nth-child(6) > ul li > a { + font: normal normal var(--font-weight-bold) 11px/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(6) > p { + font: normal normal normal 11px/13px var(--body-font-family); + } +} + +@media(min-width: 767px) { /* tablet */ + footer.default { + padding: 3.625rem 0 2.6875rem; + } + + footer.default .footer > div > :nth-child(1) > ul li > a { + font: normal normal var(--font-weight-boldest) 9pt/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(6) > ul li > a { + font: normal normal var(--font-weight-bold) 9pt/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(6) > p { + font: normal normal normal 9pt/13px var(--body-font-family); + } + + footer.landingpage img { + width: 400px; + } +} + +@media(min-width: 990px) { /* desktop */ + footer.default .footer .deactivated { + position: relative; + } + + footer.default .footer > div { + grid-template-columns: [first-col] 25% [second-col] 75%; + } + + footer.default .footer > div div { + border: none; + } + + footer.default .footer > div p { + pointer-events: none; + } + + footer.default .footer > div > :nth-child(1) { + order: 1; + display: flex; + justify-content: center; + flex-flow: row wrap; + padding: 0 3.125rem; + margin-bottom: 4.0625rem; + grid-column: first-col / span 2; + } + + footer.default .footer > div > :nth-child(1) > p { + max-width: 25%; + padding: 0; + pointer-events: visible; + } + + footer.default .footer > div > :nth-child(1) > p a img { + height: 1.75rem; + } + + footer.default .footer > div > :nth-child(1) > ul { + width: 66%; + margin-left: 9%; + display: inline-block; + vertical-align: top; + border-bottom: none; + column-count: 1; + list-style-type: none; + padding: 0; + } + + footer.default .footer > div > :nth-child(1) > ul li > a { + font: normal normal var(--font-weight-boldest) 13px/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(2) { + order: 2; + margin-top: 0; + grid-column: first-col / span 1; + padding-left: 3.125rem; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(2) > p, + footer.default .footer > div > :nth-child(3) > p, + footer.default .footer > div > :nth-child(4) > p { + padding: 0; + font: normal normal var(--font-weight-boldest) 13px/24px var(--body-font-family); + letter-spacing: 0; + color: #9098a3; + opacity: 1; + border-bottom: 1px solid #3a4350; + padding-bottom: 0.9375rem; + text-transform: none; + width: 100%; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) ul, + footer.default .footer > div > :nth-child(4) ul { + display: block !important; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) > ul { + padding: 0; + display: grid; + grid-template-columns: 1fr; + margin-top: 0.9375rem; + list-style: none; + } + + footer.default .footer > div > :nth-child(3) > p { + width: 95%; + } + + footer.default .footer > div > :nth-child(2) > ul { + padding: 0; + column-count: 1; + display: grid; + grid-template-columns: 1fr; + margin-top: 0.9375rem; + list-style: none; + } + + footer.default .footer > div > :nth-child(3) ul { + column-count: 2; + } + + footer.default .footer > div > :nth-child(2) > ul li, + footer.default .footer > div > :nth-child(4) > ul li { + margin-bottom: 0.5rem; + width: 100%; + padding: 0; + } + + footer.default .footer > div > :nth-child(2) > ul li > a, + footer.default .footer > div > :nth-child(3) > ul li > a, + footer.default .footer > div > :nth-child(4) > ul li > a { + font: normal normal var(--font-weight-bold) 13px/30px var(--body-font-family); + display: inline-block; + position: relative; + } + + footer.default .footer > div > :nth-child(3) { + order: 3; + grid-column: second-col / span 1; + margin-left: 14%; + padding-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) > p::before, + footer.default .footer > div > :nth-child(4) > p::before { + display: none; + } + + footer.default .footer > div > :nth-child(4) ul { + column-count: 3; + padding: 0; + margin-top: 0.9375rem; + } + + footer.default .footer > div > :nth-child(4) { + order: 4; + grid-column: first-col / span 2; + margin-top: 4.0625rem; + padding: 0 3.125rem; + } + + footer.default .footer > div > :nth-child(5) { + order: 5; + grid-column: first-col / span 2; + margin-top: 2.5rem; + border: none; + padding: 0 3.125rem; + margin-bottom: 0; + padding-bottom: 1rem; + } + + footer.default .footer > div > :nth-child(5) > p { + padding: 0; + } + + footer.default .footer > div > :nth-child(6) { + order: 6; + grid-column: first-col / span 2; + padding: 0 3.125rem; + } + + footer.default .footer > div > :nth-child(6) > ul { + border-top: 1px solid #3a4350; + padding: 1rem 0 0; + display: flex; + } + + footer.default .footer > div > :nth-child(6) > ul li { + display: inline-block; + list-style: none; + padding: 0; + margin: 0; + position: relative; + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-regular); + line-height: 1.14; + width: auto; + } + + footer.default .footer > div > :nth-child(6) > ul li > a { + font: normal normal normal 13px/18px var(--body-font-family); + margin-right: 0.625rem; + padding-right: 1.25rem; + position: relative; + } + + footer.default .footer > div > :nth-child(6) > ul li > a::after { + content: ""; + position: absolute; + top: 0.125rem; + right: 0.1875rem; + width: 0.125rem; + height: 1rem; + background-color: #fff; + } + + footer.default .footer > div > :nth-child(6) > p { + padding: 0; + font: normal normal normal 13px/18px var(--body-font-family); + margin-top: 0.875rem; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) > p + ul, + footer.default .footer > div > :nth-child(4) > p + ul { + overflow: visible; + max-height: 400px; + } + + footer.default .footer > div > :nth-child(4) > p.active + ul { + column-count: 3; + } +} + +#footer-ferrari { + background-color: #000; +} + +#footer-ferrari .section:nth-of-type(1) p { + width: 40%; +} + +#footer-ferrari ul { + margin-left: 0; + padding-left: 0; +} + +#footer-ferrari .section:nth-of-type(1) ul { + width: 60%; + display: flex; + justify-content: space-between; + padding-top: 0; + margin-top: 0; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) li:not(:first-of-type) { + float: left; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) li:not(:first-of-type) img { + width: 40px; + margin-right: 12px; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:first-of-type { + width: 100%; +} + +#footer-ferrari .section:nth-of-type(3) strong, +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) strong { + width: 100%; + margin-bottom: 10px; + font-size: 22px; + line-height: 27px; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:first-of-type strong { + width: 100%; + display: block; + font-size: 14px; + line-height: 1.71; + letter-spacing: 1.12px; + color: #fff; + padding-bottom: 13px; + border-bottom: 2px solid white; + margin-bottom: 25px; +} + +#footer-ferrari .section:nth-of-type(4) ul li a { + font-size: 14px; + font-weight: normal; + line-height: 1.14; + color: #fff; + position: relative; + margin-right: 10px; + padding-right: 20px; + margin-bottom: 10px; + border-right: 0 none; + display: inline-block; +} + +#footer-ferrari .section:nth-of-type(4) ul li:last-of-type a { + border-right: 0 none; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:not(:first-of-type) a { + font-size: 16px; + font-weight: 500; + line-height: 1.5; +} + +#footer-ferrari .section:nth-of-type(3) p { + border-bottom: 0 none; + margin-top: 1em; + padding-top: 10px; + font-size: 22px; + line-height: 27px; +} + +#footer-ferrari .section:nth-of-type(4) p { + text-align: right; + line-height: 17px; +} + +#footer-ferrari .section:nth-of-type(4) ul p { + font-size: 14px; + line-height: 1.14; +} + +#footer-ferrari .section:nth-of-type(1) { + display: none; +} + +#footer-ferrari .section:nth-of-type(4) ul { + width: 60%; + display: flex; + flex-direction: column; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) { + width: 100%; + margin-top: 0; +} + +#footer-ferrari .section:nth-of-type(4) { + padding-top: 0; +} + +#footer-ferrari .section:nth-of-type(4) div { + display: flex; + align-items: self-end; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) { + display: none; +} + +@media (min-width: 768px) { + footer.landingpage { + padding: 50px 0; + + .default-content-wrapper { + display: flex; + justify-content: space-between; + } + + p strong { + font-size: 32px; + font-weight: bold; + color: white; + } + } +} + +@media (min-width: 992px) { + #footer-ferrari .section:nth-of-type(1) { + display: block; + } + + #footer-ferrari .section:nth-of-type(4) ul { + display: flex; + flex-direction: row; + margin-top: 0; + margin-bottom: 0; + } + + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) { + width: 40%; + } + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) { + display: block; + width: 60%; + } + + #footer-ferrari .section:nth-of-type(3) p { + width: 100%; + border-bottom: 2px solid white; + margin-top: 100px; + padding-top: 10px; + line-height: 2; + } + + #footer-ferrari .section:nth-of-type(3) strong { + font-size: 31px; + } + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) strong { + width: 120px; + display: block; + margin-bottom: 28px; + color: #fff; + font-size: 40px; + line-height: 45px; + } + + #footer-ferrari ul li { + list-style-type: none; + padding-left: 0; + } + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:not(:first-of-type) { + width: 50%; + float: left; + margin-top: 0; + margin-bottom: 25px; + } +} + +@media(min-width: 1600px) { /* large desktop */ + footer.default .footer > div { + width: 100%; + margin: 0 auto; + padding: 0 1.25rem; + max-width: 83.25rem; + position: relative; + } +} diff --git a/_src/blocks/footer/footer.js b/_src/blocks/footer/footer.js new file mode 100644 index 000000000..6f7554873 --- /dev/null +++ b/_src/blocks/footer/footer.js @@ -0,0 +1,248 @@ +import { decorateIcons, getMetadata, loadBlocks } from '../../scripts/lib-franklin.js'; +import { adobeMcAppendVisitorId, getDomain } from '../../scripts/utils/utils.js'; +import { decorateMain } from '../../scripts/scripts.js'; + +function wrapImgsInLinks(container) { + const pictures = container.querySelectorAll('picture'); + pictures.forEach((pic) => { + const link = pic.nextElementSibling; + if (link && link.tagName === 'A' && link.href) { + link.innerHTML = pic.outerHTML; + pic.replaceWith(link); + } + }); +} + +function onFooterElementClick(evt) { + const header = evt.target; + const ul = header.nextElementSibling; + header.classList.toggle('active'); + + if (ul.classList.contains('open')) { + ul.addEventListener('transitionend', function callback() { + if (!ul.classList.contains('open')) { // Ensure the ul is still closed + ul.classList.remove('visible'); + } + ul.removeEventListener('transitionend', callback); + }); + ul.classList.remove('open'); + } else { + ul.classList.add('visible'); + setTimeout(() => { + ul.classList.add('open'); + }, 10); // slight delay to allow the browser to apply the "visible" class first + } +} + +function disableSelectedCountry(container) { + const listOfCountries = container.querySelectorAll('li'); + listOfCountries.forEach((countryLanguage) => { + if (countryLanguage.innerHTML.includes('selected')) { + countryLanguage.classList.add('deactivated'); + countryLanguage.innerHTML = countryLanguage.innerHTML.replace('(selected)', ''); + } + }); +} + +function setupPrivacyButton(container) { + const privacyButton = container.querySelector('a[href="#privacybutton"]'); + if (privacyButton) { + privacyButton.href = '#'; + privacyButton.addEventListener('click', (e) => { + e.preventDefault(); + if (window.UC_UI) { + window.UC_UI.showSecondLayer(); + } + }); + } +} + +async function runDefaultFooterLogic(block) { + // fetch footer content + const footerPath = getMetadata('footer') || '/footer'; + const resp = await fetch(`${footerPath}.plain.html`, window.location.pathname.endsWith('/footer') ? { cache: 'reload' } : {}); + + if (resp.ok) { + const html = await resp.text(); + + // decorate footer DOM + const footer = document.createElement('div'); + footer.innerHTML = html; + + wrapImgsInLinks(footer); + + const sectionHeaders = footer.querySelectorAll('div > div > p'); + sectionHeaders[2].addEventListener('click', onFooterElementClick); + sectionHeaders[3].addEventListener('click', onFooterElementClick); + + const sectionsData = footer.querySelectorAll('div > div > ul'); + disableSelectedCountry(sectionsData[3]); + + decorateIcons(footer); + block.append(footer); + + setupPrivacyButton(footer); + + adobeMcAppendVisitorId('footer'); + } +} + +async function runLandingpageLogic(block) { + const footerPath = getMetadata('footer') || '/footer'; + const resp = await fetch(`${footerPath}.plain.html`); + + const fragment = document.createElement('main'); + if (resp.ok) { + fragment.innerHTML = await resp.text(); + decorateMain(fragment); + await loadBlocks(fragment); + } + const footer = block.closest('.footer-wrapper'); + + if (window.location.href.indexOf('scuderiaferrari') !== -1 || window.location.href.indexOf('spurs') !== -1) { + block.closest('.footer-wrapper').id = 'footer-ferrari'; + } + + if (fragment) { + const fragmentSections = fragment.querySelectorAll(':scope .section'); + if (fragmentSections) { + footer.replaceChildren(...fragmentSections); + } + } + + const replacements = [ + [/\[year\]/g, new Date().getFullYear()], + [/>Twitter Bitdefenderx<'], + [/>Linkedin Bitdefenderlinkedin<'], + [/>Facebook Bitdefenderfacebook<'], + [/>Youtube Bitdefenderyoutube<'], + ]; + + replacements.forEach(([pattern, replacement]) => { + footer.innerHTML = footer.innerHTML.replace(pattern, replacement); + }); + + setupPrivacyButton(footer); + + adobeMcAppendVisitorId('footer'); +} + +async function runAemFooterLogic() { + // fetch footer content + const aemFooterHostname = window.location.hostname.includes('.hlx.') + || window.location.hostname.includes('localhost') + ? 'https://stage.bitdefender.com' + : ''; + + const websiteDomain = getDomain(); + let aemFetchDomain; + + if (websiteDomain === 'en-us') { + aemFetchDomain = 'en'; + } else if (websiteDomain.includes('-global')) { + const [singleDomain] = websiteDomain.split('-'); + aemFetchDomain = singleDomain; + } else { + aemFetchDomain = websiteDomain.split('-').join('_'); + } + + const aemFooterFetch = await fetch(`${aemFooterHostname}/content/experience-fragments/bitdefender/language_master/${aemFetchDomain}/footer-fragment-v1/master/jcr:content/root.html`); + if (!aemFooterFetch.ok) { + return; + } + + const aemFooterHtml = await aemFooterFetch.text(); + const footer = document.createElement('footer'); + const shadowRoot = footer.attachShadow({ mode: 'open' }); + const contentDiv = document.createElement('div'); + contentDiv.innerHTML = aemFooterHtml; + + const loadedLinks = []; + contentDiv.querySelectorAll('link').forEach((linkElement) => { + // update the links so that they work on all Franklin domains + linkElement.href = `${aemFooterHostname}${linkElement.getAttribute('href')}`; + linkElement.rel = 'stylesheet'; + + // add a promise for each link element in the code + // so that we can wait on all the CSS before displaying the component + loadedLinks.push(new Promise((resolve, reject) => { + linkElement.onload = () => { + resolve(); + }; + + linkElement.onerror = () => { + reject(); + }; + })); + }); + + // a list of all the components to be received from aem components + const aemComponents = ['footer']; + + // add logic so that every time an AEM function is fully loaded + // it is directly run using the shadow dom as parameter + aemComponents.forEach((aemComponentName) => { + window.addEventListener(aemComponentName, () => { + window[aemComponentName](shadowRoot); + }); + }); + + // select all the scripts from contet div and + const scripts = contentDiv.querySelectorAll('script'); + scripts.forEach((script) => { + // multiple reruns of runtime lead to all the scripts + // being run multiple times + if (!script.src.includes('runtime')) { + const newScript = document.createElement('script'); + newScript.src = `${aemFooterHostname}${script.getAttribute('src')}`; + newScript.defer = true; + shadowRoot.appendChild(newScript); + } + }); + + shadowRoot.appendChild(contentDiv); + document.querySelector('footer').replaceWith(footer); +} + +/** + * applies footer factory based on footer variation + * @param {String} footerMetadata The footer variation: landingpage' or none + * @param {Element} footer The footer element + */ +function applyFooterFactorySetup(footerMetadata, block) { + // TODO: please remove this if after creating the zh-hk and zh-tw + // headers in AEM + const regex = /\/(zh-hk|zh-tw)\//i; + const matches = window.location.href.match(regex); + if (matches) { + runDefaultFooterLogic(block); + return; + } + + switch (footerMetadata) { + case 'landingpage': + runLandingpageLogic(block); + break; + case 'franklinFooter': + runDefaultFooterLogic(block); + break; + case 'hidden': + break; + default: + runAemFooterLogic(block); + break; + } +} + +/** + * loads and decorates the footer + * @param {Element} block The footer block element + */ +export default async function decorate(block) { + const footerMetadata = getMetadata('footer-type'); + block.parentNode.classList.add(footerMetadata || 'default'); + + block.textContent = ''; + + applyFooterFactorySetup(footerMetadata, block); +} diff --git a/_src/blocks/form-blog/form-blog.css b/_src/blocks/form-blog/form-blog.css new file mode 100644 index 000000000..0c949e408 --- /dev/null +++ b/_src/blocks/form-blog/form-blog.css @@ -0,0 +1,217 @@ +.form-blog { + --input-border: #d6d6d6; + } + + .form-blog-wrapper { + width: 100%; + margin: 0 auto; + max-width: var(--body-max-width); + padding: 0 var(--body-padding); + position: relative; + } + + .form-blog > div:first-child { + display: none; + } + + .form-blog input[type="email"] { + border: 1px solid var(--input-border); + border-radius: 5px; + transition: all 0.3s ease-in-out; + font-size: var(--body-font-size-s); + line-height: 50px; + padding: 0 15px; + margin-bottom: 15px; + width: 100%; + } + + .form-blog input[type="text"] { + border: 1px solid var(--input-border); + border-radius: 5px; + transition: all 0.3s ease-in-out; + font-size: var(--body-font-size-s); + line-height: 50px; + padding: 0 15px; + margin-bottom: 15px; + width: 100%; + } + + .checkbox { + display: flex; + align-items: flex-start; + color: var(--checkbox-label); + font-size: var(--body-font-size-xs); + margin: 15px 0; + } + + .checkbox input[type="checkbox"] { + margin: 5px 10px; + width: 25px; + height: auto; + zoom: 1.25; + + @media (min-width: 768px) { + zoom: 1; + } + } + + input[type="submit"] { + width: 100%; + justify-content: center; + } + + input[type="submit"]:disabled { + opacity: 0.5; + cursor: unset; + } + + input[type="submit"]:disabled::after { + display: none; + } + + input[type="submit"].disabled:hover .button-text { + transform: none; + } + + .form-blog-container > .default-content-wrapper:nth-child(3) { + display: flex; + justify-content: center; + } + + .form-blog-container > .default-content-wrapper:nth-child(3) > p strong { + color: var( --checkbox-label); + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-bold); + } + + + .form-blog-container input[type="submit"] { + font-family: var(--body-font-family); + font-size: var(--body-font-size-s); + font-style: normal; + font-weight: var(--font-weight-bold); + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: var(--button-link-color); + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + } + + .form-blog-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1300px; + --section-desktop-padding: 20px; + --section-large-desktop-max-width: 1332px; + --section-large-desktop-padding: 50px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + } + +/* stylelint-disable-next-line no-duplicate-selectors */ +.form-blog-container{ + .form-blog-wrapper { + box-sizing: border-box; + + .form-blog.blog-template { + box-shadow: 0 5px 15px 5px rgb(0 0 0 / 10%); + max-width: 390px; + padding: 15px; + box-sizing: border-box; + + input[type="email"] { + box-sizing: border-box;; + } + + input[type="text"] { + box-sizing: border-box;; + } + + > div:first-child { + display: block; + + h2 { + font-size: 22px; + font-weight: bold; + } + + p { + font-size: 16px; + } + + p.button-container { + display: none; + } + } + } + } +} \ No newline at end of file diff --git a/_src/blocks/form-blog/form-blog.js b/_src/blocks/form-blog/form-blog.js new file mode 100644 index 000000000..85d359346 --- /dev/null +++ b/_src/blocks/form-blog/form-blog.js @@ -0,0 +1,168 @@ +import Cookie from '../../scripts/libs/cookie.js'; +import { AdobeDataLayerService, FormEvent } from '../../scripts/libs/data-layer.js'; + +function onChange(form) { + // Targeting the anchor inside .button-container + const submitButton = form.querySelector('input[type="submit"]'); + const emailInput = form.querySelector('input[type="email"]'); + + const allCheckboxesChecked = [...form.querySelectorAll('input[type="checkbox"]:required')].every((checkbox) => checkbox.checked); + const emailPopulated = emailInput.value.trim() !== ''; + + submitButton.disabled = !((allCheckboxesChecked && emailPopulated)); +} + +async function hashEmail(email) { + const encoder = new TextEncoder(); + const data = encoder.encode(email); + const hashBuffer = await crypto.subtle.digest('SHA-256', data); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join(''); + return hashHex; +} + +async function handleSubmitNewsletter(e, form, flow, successMessage, failMessage, formType = 'newsletter') { + e.preventDefault(); + const formData = new FormData(form); + const email = formData.get('email'); + const name = formData.get('name'); + const firstName = name.split(' ')[0]; + const lastName = name.split(' ')[1] || ''; + const update = formData.get('checkbox'); + + const jsonObject = { + email, + flow, + first_name: firstName, + last_name: lastName, + update, + }; + + const response = await fetch('https://www.bitdefender.com/site/Store/offerSubscribe', { + method: 'POST', + body: JSON.stringify(jsonObject), + }); + const formParent = form.parentElement; + if (response.ok) { + const hashedEmail = await hashEmail(email); + AdobeDataLayerService.push(new FormEvent( + 'form completed', + { + form: formType, + formID: hashedEmail, + }, + )); + + formParent.innerHTML = ''; + formParent.appendChild(successMessage); + + Cookie.set('newsLetterIntentShown', '1'); + } else { + formParent.innerHTML = ''; + formParent.appendChild(failMessage); + } +} + +function parseHTML(html) { + // Regular expressions to match text inside curly braces and square brackets + const curlyRegex = /{{(.*?)}}/g; + const squareRegex = /\[\[(.*?)\]\]/g; + + const insideCurlyBrackets = []; + const insideSquareBrackets = []; + + // Match all occurrences of the curly braces regex + let match; + // eslint-disable-next-line no-cond-assign + while ((match = curlyRegex.exec(html)) !== null) { + insideCurlyBrackets.push(match[1].trim()); + } + + // Match all occurrences of the square brackets regex + // eslint-disable-next-line no-cond-assign + while ((match = squareRegex.exec(html)) !== null) { + insideSquareBrackets.push(match[1].trim()); + } + + return { + insideCurlyBrackets, + insideSquareBrackets, + }; +} + +// Function to create the form +async function createForm(types, labels, flow, successMessage, failMessage, formType) { + const form = document.createElement('form'); + form.setAttribute('method', 'post'); + + for (let i = 0; i < types.length; i += 1) { + const type = types[i].toLowerCase(); + const input = document.createElement('input'); + input.id = `form-${i}-${type}`; + input.addEventListener('change', () => onChange(form)); + input.addEventListener('input', () => onChange(form)); + + if (type === 'name') { + input.setAttribute('type', 'text'); + } else { + input.setAttribute('type', type); + } + + input.setAttribute('name', type); + input.setAttribute('placeholder', labels[i]); + input.setAttribute('required', ''); + input.setAttribute('aria-required', 'true'); + + form.append(input); + if (type === 'submit') { + input.classList.add('disabled'); + input.disabled = true; + } + + if (type === 'checkbox') { + const div = document.createElement('div'); + div.classList.add('checkbox'); + + const label = document.createElement('label'); + label.setAttribute('for', `form-${i}-${type}`); + label.innerHTML = labels[i]; + input.before(div); + div.append(input, label); + } + } + + form.addEventListener('submit', (e) => handleSubmitNewsletter(e, form, flow, successMessage, failMessage, formType)); + return form; +} + +export default async function decorate(block, options) { + const { + template, flow, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const formDataHTML = block.children[1]; + const successMessage = block.children[2].children[1]; + const failMessage = block.children[3].children[1]; + const formData = parseHTML(formDataHTML.innerHTML); + const [types, labels] = [formData.insideCurlyBrackets, formData.insideSquareBrackets]; + const form = await createForm(types, labels, flow, successMessage, failMessage, options.formType); + if (form) block.append(form); + block.children[1].innerHTML = ''; + block.children[2].innerHTML = ''; + block.children[3].innerHTML = ''; + if (template === 'blog') { + block.classList.add('blog-template'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/solutions/blocks/form/form.css b/_src/blocks/form/form.css similarity index 100% rename from solutions/blocks/form/form.css rename to _src/blocks/form/form.css diff --git a/_src/blocks/form/form.js b/_src/blocks/form/form.js new file mode 100644 index 000000000..0ed943ace --- /dev/null +++ b/_src/blocks/form/form.js @@ -0,0 +1,234 @@ +async function fetchData(url) { + const resp = await fetch(url); + const json = await resp.json(); + return json.data; +} + +/** + * + * @param {String} email + * @returns {Boolean} wether the email passed is valid or not + */ +const validateEmail = (email) => { + const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return re.test(email.toLowerCase()); +}; + +/** + * + * @param {HTMLInputElement} inputElement + * @returns {Boolean} validation status of the field + */ +const checkInputValue = (inputElement) => { + // real time field validation for the email field (For DIP only) + switch (inputElement.type) { + case 'email': + // validate the email inputs using the validation function if there are error fields + if (!validateEmail(inputElement.value)) { + return false; + } + + break; + case 'checkbox': + if (!inputElement.checked && inputElement.required) { + return false; + } + + break; + default: + break; + } + + return true; +}; + +/** + * + * @param {HTMLInputElement} inputElement + */ +const displayInputError = (inputElement) => { + const inputElementError = inputElement.parentElement.querySelector('.input-error-field'); + if (inputElementError) { + inputElementError.classList.remove('global-display-none'); + } +}; + +/** + * + * @param {HTMLInputElement} inputElement + */ +const hideInputError = (inputElement) => { + const inputElementError = inputElement.parentElement.querySelector('.input-error-field'); + if (inputElementError) { + inputElementError.classList.add('global-display-none'); + } +}; + +/** + * + * @param {HTMLFormElement} form + * set the onChange function for all the form inputs + */ +function checkFormValues(form) { + const submitButton = form.querySelector('input[type="submit"]'); + + // Targeting the anchor inside .button-container + const allInputFields = form.querySelectorAll('input:not([type="hidden"])'); + let disabledStatus = false; + allInputFields.forEach((inputField) => { + if (!disabledStatus && !checkInputValue(inputField)) { + disabledStatus = true; + } + }); + + submitButton.disabled = disabledStatus; +} + +async function handleSubmit(e, handler) { + e.preventDefault(); + try { + const mod = await import(handler); + if (mod.default) await mod.default(e); + } catch (error) { + // eslint-disable-next-line no-console + console.log('failed to load module for lib-identity-exposed-onsubmit', error); + } +} + +/** + * + * @param {HTMLInputElement} input the input to be adde inside the div wrapper + * @param {HTMLDivElement} newDivParent the div wrapper to hold the input + */ +const wrapInputInsideDiv = (input, newDivParent) => { + const label = input.nextElementSibling; + + // if the input has a label, also add it inside the wrapper + if (label && label.tagName === 'LABEL') { + input.before(newDivParent); + newDivParent.append(input, label); + } else { + input.after(newDivParent); + newDivParent.append(input); + } +}; + +// Debounce function to improve performance of input calls +/** + * + * @param {Function} func + * @param {Number} wait + * @param {Boolean} immediate + */ +const debounce = (func, wait, immediate) => { + let timeout; + + return (...args) => { + const later = () => { + timeout = null; + if (!immediate) { + func(args); + } + }; + + const callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + func(args); + } + }; +}; + +/** + * + * @param {HTMLInputElement} input + * @param {HTMLFormElement} form + * add the validations which get triggered whenever an input is filled with data + */ +const addInputValidation = (input, form) => { + if (input.dataset.containsErrorField && checkInputValue(input)) { + hideInputError(input); + } else if (input.dataset.containsErrorField) { + displayInputError(input); + } + + checkFormValues(form); +}; + +/** + * + * @param {string} formURL url to form html + * @returns {Promise} returns the form + */ +export async function createForm(formURL) { + const { pathname, search } = new URL(formURL); + const data = await fetchData(`${pathname}${search}`); + const form = document.createElement('form'); + + form.setAttribute('method', 'post'); + + data.forEach((field, index) => { + const input = document.createElement('input'); + input.id = `form-${index}-${field.Field}`; + input.setAttribute('type', field.Type); + input.setAttribute('name', field.Field); + input.setAttribute('placeholder', field.Default); + input.setAttribute('value', field.Value); + input.setAttribute('data-contains-error-field', Boolean(field.Error)); + + // add event listeners to the fields + input.addEventListener('input', debounce(() => addInputValidation(input, form), 100, false)); + + if (field.Required && field.Required.toLowerCase() === 'true') { + input.setAttribute('required', ''); + input.setAttribute('aria-required', 'true'); + } + + form.append(input); + + // Only create a label if the field.Label is not null + if (field.Label) { + const label = document.createElement('label'); + label.setAttribute('for', input.id); + label.textContent = field.Label; + form.append(label); + } + + if (field.Type === 'submit') { + input.classList.add('disabled'); + input.disabled = true; + } + + if (field.Field === 'handler') { + form.addEventListener('submit', (e) => handleSubmit(e, field.Value)); + } + + if (field.Type === 'checkbox') { + const newDivWrapper = document.createElement('div'); + newDivWrapper.classList.add('checkbox'); + + wrapInputInsideDiv(input, newDivWrapper); + } + + if (field.Error) { + const newDivWrapper = document.createElement('div'); + newDivWrapper.classList.add('input-container-with-error'); + + // add the error field + const errorField = document.createElement('p'); + errorField.classList.add('input-error-field', 'global-display-none'); + errorField.textContent = field.Error; + newDivWrapper.appendChild(errorField); + input.classList.add('input-with-error-field'); + + wrapInputInsideDiv(input, newDivWrapper); + } + }); + return form; +} + +export default async function decorate(block) { + const form = await createForm(block.textContent.trim()); + if (form) block.append(form); +} diff --git a/_src/blocks/four-cards/four-cards.css b/_src/blocks/four-cards/four-cards.css new file mode 100644 index 000000000..b3af7e600 --- /dev/null +++ b/_src/blocks/four-cards/four-cards.css @@ -0,0 +1,385 @@ +.four-cards-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1300px; + --section-desktop-padding: 20px; + --section-large-desktop-max-width: 1332px; + --section-large-desktop-padding: 50px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); +} + +@media (min-width: 992px) { /* desktop */ + .four-cards-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +@media (min-width: 1600px) { /* large desktop */ + .four-cards-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +.creators .title-size .default-content-wrapper p { + font-size: 24px; +} + + +.creator-cards .four-cards.block { + display: flex; + justify-content: center; +} + +.creator-cards .four-cards.block ul li strong { + font-size: 22px; +} + +.four-cards .default-content-wrapper { + text-align: center; +} + +.creator-cards .default-content-wrapper { + text-align: center; +} + +.dlp.four-cards-container .default-content-wrapper{ + text-align: center; +} + +.four-cards-container h3 { + font: normal normal bold 32px/37px var(--body-font-family); + text-align: center; + margin-bottom: 56px; +} + +.creator-cards.four-cards-container h3 { + font: normal normal bold 60px/69px "IBM Plex Sans", sans-serif; + text-align: center; + margin-bottom: 28px; +} + +.creator-cards.four-cards-container h4 { + font: normal normal bold 22px/24px "IBM Plex Sans", sans-serif; + text-align: left; + +} + +.four-cards-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.four-cards-container .icon svg { + width: 48px; + height: 48px; + padding-right: 2px; + fill: #fff; +} + +.four-cards > ul { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: 1fr; + grid-gap: 24px; +} + +.four-cards > ul > li { + display: inline-block; + background-color: #f6f6f6; + padding: 24px; + margin: 0; + border-radius: 20px; + text-align: left; + font: normal normal normal 16px/24px var(--body-font-family); +} + +.white-background .four-cards > ul > li { + background-color: #fff; +} + +.affiliate .four-cards > ul > li { + flex: 0 1 31%; +} + +.creator-cards .four-cards > ul > li { + font-size: 18px; +} + +.creator-cards .default-content-wrapper:last-of-type { + padding-top: 0; +} + +.creator-cards .four-cards ul li div img { + height: 48px; + margin-bottom: 0; +} + +/* a/b test styles, should be deleted after */ +.four-cards-container.we-container .default-content-wrapper { + text-align: center; +} + +.four-cards-container a { + font: normal normal bold 16px/20px var(--body-font-family); + margin-top: 32px; + padding: 14px 28px; + color: #006EFF; + background: white; + border: 2px solid #006EFF; + border-radius: 10px; + display: inline-block; + position: relative; + min-width: 180px; +} + +.four-cards-container p a { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + justify-content: center; + cursor: pointer; + color: #006DFF; + background-color: transparent; + border: 2px solid #006DFF; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + transition: all .2s cubic-bezier(.4,0,.2,1); +} + +.four-cards-container p a:hover { + color: white; + background-color: var(--button-hover-background-color); +} + +.four-cards-container p a:active { + background-color: var(--button-background-color); +} + +.creator-cards .default-content-wrapper a.button:any-link { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px / 24px Roboto, sans-serif; + color: white; +} + +.creator-cards .default-content-wrapper a.button:hover { + color: white; + background-color: var(--button-background-color); +} + +.creator-cards .default-content-wrapper a.button:active { + color: white; + background-color: var(--button-background-color); + border: 0; +} + +.four-cards .icon { + width: 48px; + height: 48px; + margin-bottom: 16px; +} + +.four-cards-container.dotted-lines { + ul { + li:not(:first-child) { + position: relative; + + &::before { + content: ""; + display: block; + width: 1px; + height: 24px; + border: none; + border-left: 2px dotted #006EFF; + position: absolute; + top: -24px; + left: 50%; + } + } + } +} + +@media (max-width: 991px) { /* mobile/tablet */ + .four-cards-wrapper { + padding: var(--body-padding); + } + + .four-cards > ul > li { + margin: 0; + } +} + +@media (min-width: 768px) { + .four-cards > ul { + grid-template-columns: 1fr 1fr; + grid-gap: 14px; + } + + .four-cards-container.dotted-lines { + ul { + li:not(:first-child) { + &::before { + display: none; + } + } + } + } +} + +@media (min-width: 992px) { + .four-cards-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .four-cards > ul { + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-gap: 14px; + } + + .affiliate .four-cards > ul { + display: flex; + flex-wrap: wrap; + gap: 20px; + justify-content: center; + } + + .four-cards-container.dotted-lines { + ul { + li:not(:first-child) { + position: relative; + + &::before { + content: ""; + display: block; + width: 30px; + height: 1px; + border: none; + border-top: 2px dotted #006EFF; + margin: 24px 0; + position: absolute; + top: 50%; + left: -30px; + } + } + } + } + + .creator-cards .four-cards > ul { + grid-template-columns: 300px 300px 300px; + grid-gap: 14px; + } + + .four-cards-container.dotted-lines .four-cards > ul { + grid-gap: 30px; + } +} + +@media (min-width: 1200px) { + .four-cards-container.we-container { + max-width: 1350px; + padding-left: 20px; + padding-right: 20px; + } + +} + +@media (max-width: 991px) { + .creators .title-size .default-content-wrapper h2 { + font-size: 31px; + } + + .creators .title-size .default-content-wrapper p { + font-size: 18px; + line-height: 1.25; + margin-bottom: 9px; + } + + .creator-cards .default-content-wrapper a.button:any-link { + margin-top: 0; + } +} diff --git a/_src/blocks/four-cards/four-cards.js b/_src/blocks/four-cards/four-cards.js new file mode 100644 index 000000000..897205f78 --- /dev/null +++ b/_src/blocks/four-cards/four-cards.js @@ -0,0 +1,54 @@ +import { matchHeights } from '../../scripts/utils/utils.js'; + +export default async function decorate(block, options) { + const { + // eslint-disable-next-line no-unused-vars + margintop, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + const fourCardsWrapper = block.closest('.four-cards-wrapper'); + if (fourCardsWrapper) { + fourCardsWrapper.classList.remove('four-cards-wrapper'); + } + } + + if (margintop) { + const blockParent = block.closest('.section'); + blockParent.style.marginTop = `${margintop}px`; + } + + const ul = document.createElement('ul'); + [...block.children].forEach((row) => { + const li = document.createElement('li'); + li.innerHTML = row.innerHTML; + + ul.append(li); + }); + + block.textContent = ''; + block.append(ul); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + + // decorate icons only if the component is being called from www-websites + const isInLandingPages = window.location.href.includes('www-landing-pages') || window.location.href.includes('bitdefender.com/pages'); + if (!options && !isInLandingPages) { + const { decorateIcons } = await import('../../scripts/lib-franklin.js'); + decorateIcons(block.closest('.section')); + } + + if (isInLandingPages) { + const { decorateIcons } = await import('../../scripts/utils/utils.js'); + decorateIcons(block.closest('.section')); + } + + matchHeights(block, 'h3'); +} diff --git a/solutions/blocks/fragment-metadata/fragment-metadata.css b/_src/blocks/fragment-metadata/fragment-metadata.css similarity index 100% rename from solutions/blocks/fragment-metadata/fragment-metadata.css rename to _src/blocks/fragment-metadata/fragment-metadata.css diff --git a/solutions/blocks/fragment-metadata/fragment-metadata.js b/_src/blocks/fragment-metadata/fragment-metadata.js similarity index 64% rename from solutions/blocks/fragment-metadata/fragment-metadata.js rename to _src/blocks/fragment-metadata/fragment-metadata.js index 9f6e09365..d727c8d01 100644 --- a/solutions/blocks/fragment-metadata/fragment-metadata.js +++ b/_src/blocks/fragment-metadata/fragment-metadata.js @@ -1,5 +1,5 @@ import { readBlockConfig } from '../../scripts/lib-franklin.js'; -import { openUrlForOs } from '../../scripts/scripts.js'; +import { openUrlForOs } from '../../scripts/utils/utils.js'; export default function decorate(block) { const { @@ -11,7 +11,13 @@ export default function decorate(block) { } = readBlockConfig(block); if (template) { - document.body.classList.add(template); + // make sure that the added class is a string + // not a variable caught between '{' and '}' + const variableRegex = /^\{([\s\S]*)\}$/; + const variableMatch = template.match(variableRegex); + const classTemplate = variableMatch ? variableMatch[1] : template; + + document.body.classList.add(classTemplate); } if (urlMacos || urlWindows || urlAndroid || urlIos) { diff --git a/_src/blocks/fragment/fragment.css b/_src/blocks/fragment/fragment.css new file mode 100644 index 000000000..2001f74ab --- /dev/null +++ b/_src/blocks/fragment/fragment.css @@ -0,0 +1,3 @@ +.fragment { + z-index: 1; +} \ No newline at end of file diff --git a/_src/blocks/fragment/fragment.js b/_src/blocks/fragment/fragment.js new file mode 100644 index 000000000..8caf08b4f --- /dev/null +++ b/_src/blocks/fragment/fragment.js @@ -0,0 +1,53 @@ +/* + * Fragment Block + * Include content from one Helix page in another. + * https://www.hlx.live/developer/block-collection/fragment + */ + +import { + decorateMain, getLanguageCountryFromPath, +} from '../../scripts/scripts.js'; + +import { + loadBlocks, +} from '../../scripts/lib-franklin.js'; + +/** + * Loads a fragment. + * @param {string} path The path to the fragment + * @returns {HTMLElement} The root element of the fragment + */ +async function loadFragment(path) { + const { country, language } = getLanguageCountryFromPath(); + if (path && path.startsWith('/')) { + try { + // eslint-disable-next-line no-param-reassign + path = path.replace(/lang/g, `${language}-${country}`); + } catch (error) { + // eslint-disable-next-line no-console + console.log(error); + } + const resp = await fetch(`${path}.plain.html`); + if (resp.ok) { + const main = document.createElement('main'); + main.innerHTML = await resp.text(); + decorateMain(main); + await loadBlocks(main); + return main; + } + } + return null; +} + +export default async function decorate(block) { + const link = block.querySelector('a'); + const path = link ? link.getAttribute('href') : block.textContent.trim(); + const fragment = await loadFragment(path); + if (fragment) { + const fragmentSection = fragment.querySelector(':scope .section'); + if (fragmentSection) { + block.closest('.section').classList.add(...fragmentSection.classList); + block.closest('.fragment-wrapper').replaceWith(...fragmentSection.childNodes); + } + } +} diff --git a/_src/blocks/header-aem/header-aem.css b/_src/blocks/header-aem/header-aem.css new file mode 100644 index 000000000..825d7e3c9 --- /dev/null +++ b/_src/blocks/header-aem/header-aem.css @@ -0,0 +1,50 @@ +.header-aem-wrapper { + .header-aem { + display: flex; + align-items: center; + height: 60px; + + img { + height: 26px; + width: auto; + } + } +} + +.header-aem-container { + background-color: #fff; + border-bottom: 1px solid #EDEDED; +} + +.header-aem-wrapper.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +@media (min-width: 992px) { + .header-aem-wrapper.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .header-aem-wrapper.we-container { + max-width: 1210px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1599px) { + .header-aem-wrapper.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} diff --git a/_src/blocks/header-aem/header-aem.js b/_src/blocks/header-aem/header-aem.js new file mode 100644 index 000000000..bbe10d78d --- /dev/null +++ b/_src/blocks/header-aem/header-aem.js @@ -0,0 +1,49 @@ +async function runWhitePageHeaderLogic(block, link) { + block.classList.add('white', 'py-3', 'default-content-wrapper'); + + if (link) { + // create a link and inside it put the logo + const logoLink = document.createElement('a'); + logoLink.href = link; + logoLink.classList.add('logo-link'); + const image = block.querySelector('picture'); + logoLink.appendChild(image); + block.appendChild(logoLink); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} + +/** + * applies header factory based on header variation + * @param {String} headerMetadata The header variation: landingpage' or none + * @param {Element} header The header element + */ +function applyHeaderFactorySetup(headerMetadata, header, link) { + switch (headerMetadata) { + case 'white': + runWhitePageHeaderLogic(header, link); + break; + default: + break; + } +} +export default async function decorate(block, options) { + const { + header, link, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.header-aem-wrapper'); + blockParent.classList.add('we-container'); + } + + block.parentNode.classList.add(header || 'default'); + + applyHeaderFactorySetup(header, block, link); +} diff --git a/_src/blocks/header/header.css b/_src/blocks/header/header.css new file mode 100644 index 000000000..b44c5d82e --- /dev/null +++ b/_src/blocks/header/header.css @@ -0,0 +1,1249 @@ +/* stylelint-disable no-descending-specificity */ + +/* header and nav layout */ +header.header-wrapper { + position: sticky; + top: 0; + transition: height 0.3s ease-in-out; + background-color: var(--white-color); + z-index: 100; +} + +header.header-wrapper nav { + display: none; +} + + +:root { + --dark-header-icon-color: #000; +} + +header.header-wrapper p { + margin: 0; +} + +header.header-wrapper > p { + margin-top: 0; + padding: 15px; + text-align: center; + font-size: var(--body-font-size-s); + color: var(--horizontal-separator-color); + text-decoration: none; + cursor: pointer; + width: 175px; + height: 50px; +} + + + + + + +header.header-wrapper .nav-wrapper { + display: none; +} + +header.header-wrapper .nav-brand, +header.header-wrapper .nav-sections { + display: inline-flex; + align-items: flex-start; + width: 49.5%; +} + +header.header-wrapper .nav-brand { + flex-wrap: nowrap; + justify-content: flex-start; +} + +header.header-wrapper .nav-sections { + flex-wrap: nowrap; + justify-content: flex-end; +} + +header.header-wrapper .nav-brand p, +header.header-wrapper .nav-sections p { + display: inline-block; +} + +header.header-wrapper .bottom-links div, .bottom-links p{ + display: inline-block; +} + +header.header-wrapper .login-modal > p { + position: relative; + width: 100%; + display: block; + text-align: center; + margin-top: 45px; +} + +@keyframes animate-bottom-border { + 0% { + transform: scaleX(0); + transform-origin: left; + } + + 100% { + transform: scaleX(1); + transform-origin: left; + } +} + +header.header-wrapper .home-button-border { + position: absolute; + margin-top: 12px; + width: 70px; + height: 3px; + background-color: var(--color-highlight-blue); +} + +header.header-wrapper .nav-divider { + display: flex; + flex-wrap: nowrap; + justify-content: flex-end; + min-width: 2px; + width: 2px; + background-color: var(--color-dark-gray); + height: 20px; + margin-right: 15px; + margin-top: 7.5px; +} + +header.header-wrapper .login-modal { + display: none; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + position: absolute; + right: min(15px, calc(100vw - 880px)); + width: 375px; + height: 275px; + top: 80px; + background-color: var(--background-color); + border-radius: 5px; + opacity: 0; + transition: all 0.3s ease-in-out; + box-shadow: 0 10px 10px #0003; + z-index: 0; + transform: translateY(20px); +} + +header.header-wrapper .login-modal.show { + opacity: 1; + top: 60px; + z-index: 5; + transform: translateY(0); +} + + +header.header-wrapper .login-modal h2 { + position: relative; + white-space: nowrap; + color: var(--text-color); + font-size: var(--body-font-size-s); + width: 100%; + margin-left: 25px; + top: 15px; + text-align: left; +} + +header.header-wrapper .divider { + position: absolute; + margin-top: 45px; + width: 100%; + height: 1px; + background-color: var(--color-dark-gray); +} + +.login-modal a { + text-decoration: none; + color: var(--color-highlight-blue) !important; + width: 330px; + height: 55px; + border-radius: 9px; + border: 2px solid var(--color-highlight-blue) !important; + background-color: transparent !important; + margin: -70px; + padding: 5px; + display: inline-block; + font-size: var(--body-font-size-xs); + font-weight: 500; +} + +header.header-wrapper a.button:any-link { + padding: 0; +} + +header.header-wrapper .login-modal a.button:any-link { + height: 50px; + padding-right: 15px; +} + +header.header-wrapper a.button::after { + margin-left: 0; +} + +header.header-wrapper .login-modal a.button::after { + position: relative; + margin-left: 220px; +} + +header.header-wrapper .login-modal a.button:any-link span { + margin-left: 25%; + position: absolute; + font-weight: 500; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(3) span { + margin-left: 13%; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(3) a.button::after { + margin-left: 280px; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(4) span { + margin-left: 33%; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(4) a.button::after { + margin-left: 200px; +} + +header.header-wrapper .logo-container { + height: 100%; + display: flex; + justify-content: start; + align-items: center; + max-width: var(--section-desktop-max-width); + margin: 0 auto; + padding: 0 var(--body-padding); +} + +header.header-wrapper.expanded .logo-container { + height: var(--nav-height); + position: absolute; + top: 0; + left: 0; +} + +header.header-wrapper .logo-container > p { + display: none; +} + +header.header-wrapper .login-buttons a p { + text-align: center; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + margin-top: 5px; + transition: all 0.3s ease-in-out; + height: 100%; +} + +header.header-wrapper .icon { + position: absolute; + margin: 0; + z-index: 1000; + top: 15px; + width: 103px; + height: 30px; + filter: none; + left: 20px; + color: var(--dark-background-color); +} + +header.header-wrapper .bottom-links p > a { + text-decoration: none; + font-size: var(--body-font-size-xxs) !important; + font-weight: 500 !important; +} + +header.header-wrapper .login-modal a:hover { + background-color: var(--color-highlight-blue) !important; + color: var(--background-color) !important; +} + +header.header-wrapper a.button span.button-text { + display: flex; + font-size: var(--body-font-size-xs); + font-weight: 400; +} + +header.header-wrapper a.button:hover span.button-text { + transform: none; +} + +header.header-wrapper .options-wrapper.show a { + display: block; + margin-left: 40px; + color: var(--text-color); + font-size: var(--body-font-size-xs); + margin-top: 10px; + text-decoration: none; + animation: slide-in 0.2s 0.075s forwards; + background-color: transparent !important; + border: transparent !important; +} + +header.header-wrapper .bottom-links p:hover > a { + color: var(--color-highlight-blue) !important; +} + +header.header-wrapper > p a:hover{ + color: var(--background-color); +} + +header.header-wrapper .options-wrapper.show > a:first-child { + margin-top: 40px; +} + +header.header-wrapper .login-modal.show.button-container a:hover{ + background-color: var(--color-highlight-blue); + color: var(--background-color); +} + +header.header-wrapper .triangle { + position: absolute; + width: 0; + height: 0; + top: -13px; + left: 320px; + border-left: 15px solid transparent; + border-right: 15px solid transparent; + border-bottom: 20px solid white; +} + +header.header-wrapper .mega-menu-websites div h2 { + position: relative; + font-size: var(--body-font-size-s); + font-weight: 600; + margin-left: 25px; +} + +header.header-wrapper .mega-menu-websites > div:first-child { + display: grid; + grid-template-rows: auto auto; + grid-template-columns: 1fr 1fr 1fr; + align-items: start; + border-bottom: 2px solid #f5f6f7; +} + +header.header-wrapper .mega-menu-websites > div:first-child h2 { + grid-column: span 3; +} + +header.header-wrapper .mega-menu-websites > div:first-child p { + width: 250px; + margin-top: 5px; + border-radius: 5px; + padding: 10px; + height: 85px; +} + + +header.header-wrapper .mega-menu-websites > div:first-child p:hover { + background-color: var(--highlight-light-blue); +} + +header.header-wrapper .mega-menu-websites > div:first-child > p:first-child { + grid-column: 1; +} + +header.header-wrapper .mega-menu-websites > div:first-child p a > span::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + opacity: 0; +} + +header.header-wrapper .mega-menu-websites > div:first-child p a:hover span::after { + opacity: 1; + background-color: var(--color-highlight-blue); +} + +header.header-wrapper .mega-menu-websites > div:first-child p a::after { + display: none; +} + +header.header-wrapper .options-wrapper.show div { + font-weight: var(--font-weight-bold); + font-size: var(--body-font-size-s); + margin: 25px 13px 25px 20px; + position: relative; +} + +header.header-wrapper .options-wrapper.show div::before { + border-color: black; + border-style: solid; + border-width: 0 2px 2px 0; + content: ""; + width: 0.5rem; + height: 0.5rem; + display: inline-block; + position: absolute; + right: 10px; + top: 50%; + transform: translateY(-50%) rotate(-45deg); +} + +@media (max-width: 992px) { + header.header-wrapper .nav-wrapper { + display: none; + } + + header.header-wrapper p { + margin: 0; + } + + header.header-wrapper > p{ + display: none; + } + +} + +header.header-wrapper .icon.icon-arrow-right { + position: absolute; + width: 10px; + height: 10px; + margin-left: 1px; + z-index: 5; +} + +header.header-wrapper .bottom-links div:nth-child(2) { + margin-left: 120px; +} + +header.header-wrapper .menu-bar { + display: block; + width: 100%; + height: 3px; + background-color: var(--text-color); + transition: transform 0.3s ease, opacity 0.3s ease; + will-change: transform, opacity; +} + +header.header-wrapper .menu-wrapper { + position: absolute; + top: 17px; + right: 20px; + width: 25px; + height: 25px; + cursor: pointer; + display: flex; + flex-direction: column; + justify-content: space-around; + z-index: 100; +} + +header.header-wrapper .menu-wrapper.change .menu-bar:first-child { + transform: rotate(-45deg) translate(-5px, 5px); +} + +header.header-wrapper .menu-wrapper.change .menu-bar:nth-child(2) { + opacity: 0; +} + +header.header-wrapper .menu-wrapper.change .menu-bar:last-child { + transform: rotate(45deg) translate(-6px,-7px); +} + +header.header-wrapper.expanded { + height: 100vh; + width: 100vw; + z-index: 2; +} + +header.header-wrapper .options-wrapper { + position: relative; + top: var(--nav-height); + width: 100vw; + height: 0; + display: none; +} + +header.header-wrapper .options-wrapper.show{ + width: 100vw; + height: 100vh; + box-shadow: 0 10px 10px #0003; + z-index: 3; + border-top: 1px solid #cecccc; + display: block; +} + +header.header-wrapper .sub-menu { + display: none; +} + +header.header-wrapper .sub-menu.show { + display: block; +} + +header.header-wrapper .options-wrapper.show .sub-menu-title { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + margin-left: 20px; + padding-left: 20px; + position: relative; +} + +header.header-wrapper .options-wrapper.show .sub-menu-title::before { + border-color: black; + border-style: solid; + border-width: 0 2px 2px 0; + content: ""; + width: 0.5rem; + height: 0.5rem; + display: inline-block; + position: absolute; + left: 0; + top: 50%; + transform: translate(0, -50%) rotate(135deg); +} + +@keyframes slide-in { + from { + transform: translateX(100%); + } + + to { + transform: translateX(0); + } +} + +header.header-wrapper #icons-sprite-bitdefender-logo path { + fill: currentcolor +} + +#header-ferrari { + border-bottom: 2px solid #3C3C3C; + height: 40px; + box-shadow: 0 32px 73px #000; + background-color: black; +} + +#header-ferrari div div { + margin-top: -10px; +} + +#header-ferrari ul { + padding: 0; + margin: 0; + width: 50%; + float: left; +} + +#header-ferrari ul:nth-of-type(2) { + text-align: right; +} + +#header-ferrari ul:nth-of-type(3) { + width: 100%; + margin-top: -5px; +} + +#header-ferrari ul li { + color: white; + font-size: 12px; + list-style-type: none; + display: inline-block; + padding: 0 10px; + font-weight: 600; +} + +#header-ferrari ul:nth-of-type(2) li { + border-left: 1px solid #616161; +} + +#header-ferrari ul:nth-of-type(3) li { + padding: 0 25px 0 0; +} + +#header-ferrari ul:nth-of-type(1) li:nth-of-type(1) { + padding-left: 0; +} + +#header-ferrari ul li a { + color: #DEDEDE; + font-size: 12px; + padding-bottom: 10px; + position: relative; + font-weight: 600; +} + +#header-ferrari ul li a::before { + content: ""; + position: absolute; + bottom: -2px; + height: 4px; + background: #006EFF; + transition: all 0.3s ease; + transition-property: transform; + width: 100%; + transform: scaleX(0); + will-change: transform; + transform-origin: right; +} + +#header-ferrari ul li a:hover { + text-decoration: none; +} + +#header-ferrari ul li a:hover::before { + transform: scaleX(1); + transform-origin: left; +} + +#header-ferrari ul:nth-of-type(3) li a { + color: #FFF; + font-size: 16px; + font-weight: 500; +} + +#header-ferrari ul:nth-of-type(3) li a span.icon-logo-white { + display: inline-block; + background: url("/_src/images/sigla_bd_white.svg") 0 0 no-repeat; + width: 165px; + height: 25px; +} + +#header-ferrari ul:nth-of-type(3) :nth-of-type(3) a { + font-weight: bold; +} + +header.quiz { + background: black; + + .icon { + width: 155px; + } +} + +@media(min-width: 767px) { /* tablet */ + header.header-wrapper .logo-container .icon { + width: 180px; + } + +} + +@media(min-width: 992px) { + header.header-wrapper::after { + position: absolute; + top: 64px; + left: 0; + right: 0; + width: 100%; + height: 2px; + background-color: #3c3c3c; + margin: 0 auto; + } + + header.header-wrapper .icon { + color: var(--text-color); + position: static; + } + + header.header-wrapper.black-background .icon { + color: var(--text-dark-color); + } + + header.header-wrapper .menu-wrapper { + display: none; + } + + header.header-wrapper .nav-wrapper { + width: 100%; + background-color: var(--text-color); + z-index: 100; + display: block; + margin: 0 auto; + } + + header.header-wrapper nav { + display: block; + max-width: var(--section-desktop-max-width); + height: 100%; + margin: 0 auto; + padding: 6px var(--section-desktop-padding) 10px; + position: relative; + } + + header.header-wrapper nav p { + line-height: 1.4; + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-bold); + } + + header.header-wrapper .nav-sections { + display: inline-flex; + flex-wrap: wrap; + gap: 0; + } + + + header.header-wrapper .nav-brand a, + header.header-wrapper .nav-sections a { + color: var(--horizontal-separator-color); + text-decoration: none; + text-transform: uppercase; + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-bold); + margin-right: 0; + letter-spacing: 0.96px; + cursor: pointer; + line-height: 1.4; + display: inline-block; + position: relative; + } + + header.header-wrapper .nav-sections a { + margin: 0 15.5px; + } + + header.header-wrapper .logo a { + display: block; + } + + header.header-wrapper .nav-brand p a { + margin: 0 12px; + } + + header.header-wrapper .mega-menu-websites div h2 > a { + transition: all 0.2s ease-in-out; + border-radius: 3px; + text-decoration: none; + padding: 7px 10px; + color: var(--link-color); + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + } + + header.header-wrapper .mega-menu-websites div p a{ + position: relative; + font-size: var(--body-font-size-xs); + font-weight: 400; + color: var(--text-color); + } + + header.header-wrapper .nav-sections a:first-child{ + margin-right: 16px; + } + + header.header-wrapper .nav-brand p:first-child a{ + margin-left: 0; + } + + header.header-wrapper .nav-sections p a::before, + header.header-wrapper .nav-brand p a::before { + content: ""; + position: absolute; + top: 25px; + height: 3px; + background: var(--color-highlight-blue); + transition: all .3s ease; + width: 100%; + transform: scaleX(0); + transform-origin: left; + left: 0; + } + + header.header-wrapper .nav-sections p a:hover::before, + header.header-wrapper .nav-brand p a.active::before, + header.header-wrapper .nav-brand p a:hover::before, + header.header-wrapper .nav-sections p.clicked a::before { + transform: scaleX(1); + transform-origin: left; + } + + /* Other existing styles */ + header.header-wrapper .mega-menu-websites div h2 > a:hover { + background-color: var(--highlight-light-blue); + } + + header.header-wrapper .nav-sections p:last-child:hover::after { + width: 50px; + } + + header.header-wrapper .nav-sections p, + header.header-wrapper .nav-brand p { + position: relative; + } + + header.header-wrapper .nav-sections p::before, + header.header-wrapper .nav-brand p:not(:first-child)::before { + content: ""; + position: absolute; + top: 0; + left: 0; + height: 16px; + width: 2px; + background-color: #616161; + } + + header.header-wrapper .logo-container { + padding: 20px var(--section-desktop-padding); + margin: 21px auto 0; + gap: 10px; + } + + header.header-wrapper .logo-container > p { + display: block; + font-weight: var(--font-weight-bold); + line-height: 1.63; + font-size: 15px; + } + + header.header-wrapper .home-solutions-link-hover { + color: #FFF; + } + + header.header-wrapper .home-solutions-link-default { + display: block; + color: var(--text-color); + cursor: pointer; + padding: 0 27px 31px; + position: relative; + margin-top: 35px; + } + + header.header-wrapper.black-background .home-solutions-link-default { + color: #dedede; + } + + header.header-wrapper .home-solutions-link-default::before { + content: ""; + position: absolute; + bottom: 3px; + height: 4px; + background: #006eff; + transition: all .3s ease; + width: 100%; + transform: scaleX(0); + transform-origin: left; + left: 0; + } + + header.header-wrapper .home-solutions-link-hover::before { + transform: scaleX(1); + transform-origin: left; + } + + header.header-wrapper .mega-menu-websites { + flex-direction: column; + position: absolute; + left: 80px; + top: 123px; + max-width: 920px; + width: 100%; + background-color: var(--background-color); + z-index: 3; + transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + box-shadow: 0 10px 10px #0003; + visibility: hidden; + display: none; + opacity: 0; + } + + header.header-wrapper .mega-menu-websites-show { + opacity: 1; + visibility: visible; + display: flex; + } + + header.header-wrapper .mega-menu-websites div h2 { + position: relative; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-boldest); + line-height: 18px; + padding: 7px 10px; + margin: 10px 25px 0 15px; + } + + header.header-wrapper .other-options > div:nth-child(5) { + grid-area: 2 / 3 / 3 / 4; + } + + header.header-wrapper .other-options > div:nth-child(4) { + grid-area: 2 / 2 / 3 / 3; + } + + header.header-wrapper .other-options > div:nth-child(3) { + grid-area: 1 / 3 / 2 / 4; + } + + header.header-wrapper .other-options > div:nth-child(2) { + grid-area: 1 / 2 / 2 / 3; + } + + header.header-wrapper .other-options > div:nth-child(1) { + grid-area: 1 / 1 / 3 / 2; + } + + header.header-wrapper .other-options > div > p { + position: relative; + top: 0; + margin-left: 20px; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-regular); + line-height: 18px; + } + + header.header-wrapper .other-options > div > h2 { + margin-top: 0; + } + + header.header-wrapper .other-options > div > p a.button { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-regular); + line-height: 18px; + text-decoration: none; + padding: 1px 10px; + background-color: transparent; + border-radius: 4px; + border: none; + } + + header.header-wrapper .other-options > div > p a.button:hover { + background-color: var(--highlight-light-blue); + transition: none; + transform: none; + } + + header.header-wrapper .mega-menu-websites > div:first-child p a::after { + display: none; + } + + header.header-wrapper .other-options > div > p a:hover::after { + background-color: var(--color-highlight-blue); + } + + header.header-wrapper .other-options > div > p a.button > span { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-regular); + line-height: 18px; + position: relative; + color: var(--text-color); + } + + header.header-wrapper .mega-menu-websites > div:first-child p a > span:first-child { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-boldest); + line-height: 18px; + align-items: center; + } + + header.header-wrapper .mega-menu-websites .button-container:hover a.button::after { + transform: none; + opacity: 1; + } + + header.header-wrapper .mega-menu-websites > div:first-child { + display: grid; + grid-template-rows: auto auto; + grid-template-columns: 1fr 1fr 1fr; + align-items: start; + border-bottom: 2px solid #f5f6f7; + padding-bottom: 14px; + } + + header.header-wrapper.mega-menu-websites > div:first-child > p > a > div { + margin-top: 5px; + line-height: 18px; + font-size: 13px; + font-weight: 400; + color: var(--color-dark-gray); + white-space: break-spaces; + text-align: left; + } + + header.header-wrapper .mega-menu-websites > div:first-child h2 { + grid-column: span 3; + } + + header.header-wrapper .mega-menu-websites div p { + margin-left: 15px; + } + + header.header-wrapper.bottom-links div p { + height: fit-content; + margin-left: 20px; + } + + header.header-wrapper .mega-menu-websites > div:first-child p { + width: 250px; + margin-top: 0; + border-radius: 5px; + padding: 0; + height: auto; + } + + header.header-wrapper .mega-menu-websites > div:first-child p:hover { + background-color: var(--highlight-light-blue); + } + + header.header-wrapper .mega-menu-websites > div:first-child > p:first-child { + grid-column: 1; + } + + header.header-wrapper .mega-menu-websites > div:first-child p a > span::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + opacity: 0; + } + + header.header-wrapper .mega-menu-websites > div:first-child p a:hover > span::after { + opacity: 1; + background-color: var(--color-highlight-blue); + } + + + header.header-wrapper .mega-menu-websites > div:first-child p a { + padding: 7px 10px; + display: block; + color: var(--text-color) !important; + text-decoration: none; + font-size: var(--body-font-size-s); + background-color: transparent; + border: none; + } + + header.header-wrapper .mega-menu-websites > div:first-child p:hover a { + color: var(--color-highlight-blue) !important; + } + + header.header-wrapper .other-options { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: repeat(2, 1fr); + grid-gap: 0; + padding-top: 14px; + } + + header.header-wrapper #new, + header.header-wrapper #evolved { + position: relative; + font-size: var(--body-font-size-xxs); + font-weight: 600; + color: var(--background-color); + background-color: var(--color-highlight-blue); + padding: 2px; + border-radius: 3px; + margin-left: 5px; + } + + header.header-wrapper .bottom-links { + background-color: rgb(158 164 177 / 10%); + padding: 8px 11px; + margin-top: 20px; + } + + header.quiz { + height: unset; + + .icon { + width: 200px; + height: 64px; + } + } +} + +@media (min-width: 1200px) { + header.header-wrapper .mega-menu-websites { + left: 80px; + transform: translateX(0); + } +} + +@media (min-width: 1400px) { + header.header-wrapper .mega-menu-websites { + left: 210px; + transform: translateX(0); + } +} + +@media (min-width: 1600px) { + header.header-wrapper .mega-menu-websites { + left: 240px; + transform: translateX(0); + } +} + +@media (min-width: 1600px) { + header.header-wrapper nav { + max-width: var(--section-large-desktop-max-width); + padding-left: var(--section-large-desktop-padding); + padding-right: var(--section-large-desktop-padding); + } + + header.header-wrapper .nav-brand p a { + margin: 0 19px; + } + + header.header-wrapper .logo-container { + max-width: var(--section-large-desktop-max-width); + padding-left: var(--section-large-desktop-padding); + padding-right: var(--section-large-desktop-padding); + } + + header.header-wrapper .logo-container > p { + font-size: 16px; + } + + header.header-wrapper .home-solutions-link-default { + padding-left: 20px; + } +} + +/* import header spurs lp */ +@media screen and (max-width: 989px) { + #header-ferrari.header-spurs { + background-color: white; + border-bottom: 0 none; + height: 40px; + position: static; + } + + #header-ferrari.header-spurs::before { + content: ''; + background: url('/_src/images/black_company_logo.svg') no-repeat 0 0 transparent; + width: 100px; + height: 20px; + display: block; + background-size: 100%; + margin: 10px; + position: relative; + top: 7px; + } + + #header-ferrari.header-spurs .lp-header { + padding: 0!important; + } + + #header-ferrari.header-spurs .lp-header::before { + content: ''; + background: url('/_src/icons/burger_menu.JPG') no-repeat 0 0 transparent; + width: 29px; + height: 29px; + display: block; + background-size: 100%; + position: absolute; + right: 7px; + top: -26px; + cursor: pointer; + } + + #header-ferrari.header-spurs .lp-header > div { + position: absolute; + z-index: 5; + background-color: white; + width: 100%; + visibility: hidden; + } + + #header-ferrari.header-spurs .lp-header.active > div { + visibility: visible; + } + + #header-ferrari.header-spurs .lp-header > div ul li { + border-bottom: 1px solid #0003; + padding-left: 15px; + } + + .btn-white .button-container a, .btn-white.button-container a:hover { + font-size: 14px; + line-height: 17px; + padding: 10px 1em; + } + + #header-ferrari.header-spurs .lp-header > div ul li, #header-ferrari.header-spurs .lp-header > div ul li a { + width: 100%; + display: block; + padding-bottom: 0; + color: black; + font-size: 15px; + font-family: 'IBM Plex Sans', sans-serif; + text-transform: uppercase; + } + + #header-ferrari.header-spurs .lp-header > div ul li a::before { + display: none; + } + + #header-ferrari.header-spurs ul:last-of-type li:first-of-type { + display: none; + } + + + #header-ferrari { + box-shadow: none; + position: static; + height: auto; + } + + #header-ferrari div div { + margin-top: 0; + flex-direction: column; + display: flex; + } + + #header-ferrari ul { + width: 100%; + float: none; + } + + #header-ferrari ul:nth-of-type(1) { + order: 2; + } + + #header-ferrari ul:nth-of-type(2) { + text-align: left; + order: 3; + } + + #header-ferrari ul li { + padding: 0 10px 0 0; + font-size: 12px; + } + + #flipdown .flip-clock-wrapper ul li { + line-height: 48px; + } + + #header-ferrari ul:nth-of-type(2) li { + border-left: 0 none; + } + + #header-ferrari ul:nth-of-type(3) { + margin-top: 0; + padding-bottom: 0; + order: 1; + } + + #header-ferrari ul:nth-of-type(3) li a span.icon-logo-white { + width: 100px; + height: 17px; + background-size: 100%; + } + + #header-ferrari ul:nth-of-type(3) li { + padding: 0 3px 0 0; + } + + #header-ferrari ul:nth-of-type(3) li a { + font-size: 12px; + } +} diff --git a/solutions/blocks/header/header.js b/_src/blocks/header/header.js similarity index 56% rename from solutions/blocks/header/header.js rename to _src/blocks/header/header.js index 3ec8f51e3..24c6c9545 100644 --- a/solutions/blocks/header/header.js +++ b/_src/blocks/header/header.js @@ -2,8 +2,111 @@ import { getMetadata, decorateIcons, decorateButtons, decorateTags, } from '../../scripts/lib-franklin.js'; -import { decorateBlockWithRegionId, decorateLinkWithLinkTrackingId } from '../../scripts/scripts.js'; -import { adobeMcAppendVisitorId } from '../../scripts/utils.js'; +import { + adobeMcAppendVisitorId, getDomain, decorateBlockWithRegionId, decorateLinkWithLinkTrackingId, +} from '../../scripts/utils/utils.js'; + +import { User } from '../../scripts/libs/user.js'; +import Cookie from '../../scripts/libs/cookie.js'; +import { Constants } from '../../scripts/libs/constants.js'; +import { Visitor } from '../../scripts/libs/data-layer.js'; + +/** + * @param {string} username + * @param {string} email + * @param {HTMLLIElement} newMegaMenuLoginTab + * updates the mega menu login popup and avatar + */ +const updateMegaMenu = (username, email, newMegaMenuLoginTab) => { + let firstInitial; + let secondInitial; + + // if the cookies are still valid update the menu + if (username) { + const splitUserName = username.split(' '); + firstInitial = splitUserName[0].charAt(0).toUpperCase(); + // eslint-disable-next-line no-nested-ternary + secondInitial = splitUserName.length > 1 + ? splitUserName[1].charAt(0).toUpperCase() + : (splitUserName[0].length > 1 ? splitUserName[0].charAt(1).toUpperCase() : ''); + } else { + const splitEmail = email.split('@')[0].replace(/[^a-zA-Z]+/g, ''); + firstInitial = splitEmail.charAt(0).toUpperCase(); + secondInitial = splitEmail.length > 1 ? splitEmail.charAt(1).toUpperCase() : ''; + } + + // set user initials in the avatar section + const avatar = newMegaMenuLoginTab.querySelector('.mega-menu__right-link'); + avatar.classList.add('mega-menu__login'); + avatar.textContent = `${firstInitial}${secondInitial}`; + + // switch to the logged in popup + const loginPopup = newMegaMenuLoginTab.querySelector('.mega-menu__second-level-container'); + const loginPopupHeaderLink = loginPopup.querySelector('.mega-menu__column .navigation__header-link'); + const loginPopupLinksThatNeedToChange = [...loginPopup.querySelectorAll('.navigation__link')] + .filter((navigationLink) => navigationLink.dataset.loggedInLink); + + if (loginPopupHeaderLink) { + loginPopupHeaderLink.textContent = username + ? `${avatar.dataset.loginText}, ${username}` + : `${avatar.dataset.loginText}, ${email}`; + } + + const userLoggedInExpirationDate = Cookie.get(Constants.LOGIN_LOGGED_USER_EXPIRY_COOKIE_NAME); + + if (!userLoggedInExpirationDate + || (userLoggedInExpirationDate && userLoggedInExpirationDate > Date.now())) { + loginPopupLinksThatNeedToChange.forEach(async (loginPopupLink) => { + loginPopupLink.href = await Visitor.appendVisitorIDsTo(loginPopupLink.dataset.loggedInLink); + }); + } +}; + +/** + * @param {Element} root + * run the login logic after the menu is loaded in + */ +const loginFunctionality = async (root = document) => { + try { + // change login container to display that the user is logged in + // if the previous call was successfull + const megaMenuLoginContainer = root.querySelector('li.mega-menu__login-container'); + const loginAttempt = sessionStorage.getItem('login-attempt'); + const userData = await User.getUserInfo(); + + if (!loginAttempt && !userData) { + const userLoggedInExpirationDate = Cookie.get(Constants.LOGIN_LOGGED_USER_EXPIRY_COOKIE_NAME); + if (userLoggedInExpirationDate > Date.now()) { + sessionStorage.setItem('login-attempt', true); + const loginEndpointUrl = new URL(`${Constants.LOGIN_URL_ORIGIN}${megaMenuLoginContainer.dataset.loginEndpoint}`); + loginEndpointUrl.searchParams.set('origin', `${window.location.pathname}${window.location.search}`); + window.location.href = loginEndpointUrl.href; + } + } else if (userData) { + updateMegaMenu(userData.firstname, userData.email, megaMenuLoginContainer); + } + } catch (error) { + // eslint-disable-next-line no-console + console.warn(error); + } +}; + +function makeImagePathsAbsolute(contentDiv, baseUrl) { + contentDiv.querySelectorAll('img').forEach((imgElement) => { + // Update the `src` attribute with an absolute URL + imgElement.src = `${baseUrl}${imgElement.getAttribute('src')}`; + + // Function to update relative paths in `srcset` with absolute URLs + function makeSrcsetAbsolute(srcset) { + return srcset.replace(/(?:,|^)\s*(\/[^\s,]+)/g, (match, path) => match.replace(path, `${baseUrl}${path}`)); + } + + // Update the `srcset` attribute with absolute URLs + if (imgElement.srcset) { + imgElement.srcset = makeSrcsetAbsolute(imgElement.srcset, baseUrl); + } + }); +} function createLoginModal() { const loginModal = document.querySelector('nav > div:nth-child(4)'); @@ -34,7 +137,7 @@ function handleLoginClick() { } function appendUlToP() { - const divs = document.querySelectorAll('.mega-menu > div'); + const divs = document.querySelectorAll('.mega-menu-websites > div'); divs.forEach((div) => { const uls = div.querySelectorAll('ul'); @@ -60,7 +163,7 @@ function wrapDivsInMegaMenu() { const divs = Array.from(nav.children).filter((node) => node.tagName.toLowerCase() === 'div'); const navSectionsIndex = divs.findIndex((div) => div.classList.contains('nav-sections')); const megaMenuDiv = document.createElement('div'); - megaMenuDiv.className = 'mega-menu'; + megaMenuDiv.className = 'mega-menu-websites'; decorateBlockWithRegionId(megaMenuDiv, 'Main Menu|Home Solutions'); const otherOptionsDiv = document.createElement('div'); @@ -96,7 +199,7 @@ function wrapDivsInMegaMenu() { otherOptionsDiv.appendChild(bottomLinks.firstElementChild); } - const loginModal = document.querySelector('.mega-menu > div:first-child'); + const loginModal = document.querySelector('.mega-menu-websites > div:first-child'); nav.appendChild(loginModal); } @@ -174,20 +277,20 @@ function renderDesktopHeader(block, nav) { const bottomLinks = document.querySelector('.bottom-links'); bottomLinks.removeChild(bottomLinks.lastElementChild); - const megaMenu = document.querySelector('.mega-menu'); + const megaMenu = document.querySelector('.mega-menu-websites'); let isOverHomeSolutions = false; let isOverMegaMenu = false; const showMegaMenu = () => { megaMenu.style.display = 'flex'; setTimeout(() => { - megaMenu.classList.add('mega-menu-show'); + megaMenu.classList.add('mega-menu-websites-show'); }, 10); }; const hideMegaMenu = () => { if (!isOverHomeSolutions && !isOverMegaMenu) { - megaMenu.classList.remove('mega-menu-show'); + megaMenu.classList.remove('mega-menu-websites-show'); homeSolutions.classList.remove('home-solutions-link-hover'); } }; @@ -244,7 +347,7 @@ function handleMenuClick() { }); // Select the first child of mega-menu and all div children of other-options - const megaMenuFirstChild = document.querySelector('.mega-menu').firstElementChild; + const megaMenuFirstChild = document.querySelector('.mega-menu-websites').firstElementChild; const otherOptionsChildren = Array.from(document.querySelector('.other-options').children); const navDivs = [megaMenuFirstChild].concat(otherOptionsChildren); @@ -363,12 +466,8 @@ function renderMobileHeader(nav) { headerBlock.appendChild(optionsWrapper); } -export default async function decorate(block) { +async function runDefaultHeaderLogic(block) { const hero = document.querySelector('.hero'); - const isErrorPage = window.isErrorPage || false; - - // Check if the page isn't an error page and if the hero doesn't exist - if (!hero && !isErrorPage) return; if (hero && hero.classList.contains('black-background')) { const header = document.querySelector('header'); @@ -385,6 +484,109 @@ export default async function decorate(block) { if (resp.ok) { const html = await resp.text(); + if (html.includes('aem-banner')) { + const websiteDomain = getDomain(); + let aemFetchDomain; + + if (websiteDomain === 'en-us') { + aemFetchDomain = 'en'; + } else if (websiteDomain.includes('-global')) { + const [singleDomain] = websiteDomain.split('-'); + aemFetchDomain = singleDomain; + } else { + aemFetchDomain = websiteDomain.split('-').join('_'); + } + + const aemHeaderFetch = await fetch(`${Constants.PUBLIC_URL_ORIGIN}/content/experience-fragments/bitdefender/language_master/${aemFetchDomain}/header-navigation/mega-menu/master/jcr:content/root.html`); + if (!aemHeaderFetch.ok) { + return; + } + const aemHeaderHtml = await aemHeaderFetch.text(); + const nav = document.createElement('div'); + const shadowRoot = nav.attachShadow({ mode: 'open' }); + + const contentDiv = document.createElement('div'); + contentDiv.style.display = 'none'; + + contentDiv.innerHTML = aemHeaderHtml; + + // make image paths absolute for non-production environments + if (Constants.PUBLIC_URL_ORIGIN === 'https://stage.bitdefender.com') { + makeImagePathsAbsolute(contentDiv, Constants.PUBLIC_URL_ORIGIN); + } + + const loadedLinks = []; + contentDiv.querySelectorAll('link').forEach((linkElement) => { + // update the links so that they work on all Franklin domains + linkElement.href = `${Constants.PUBLIC_URL_ORIGIN}${linkElement.getAttribute('href')}`; + + // add a promise for each link element in the code + // so that we can wait on all the CSS before displaying the component + loadedLinks.push(new Promise((resolve, reject) => { + linkElement.onload = () => { + resolve(); + }; + + linkElement.onerror = () => { + reject(); + }; + })); + }); + + // a list of all the components to be received from aem components + const aemComponents = ['languageBanner', 'megaMenu']; + + // add logic so that every time an AEM function is fully loaded + // it is directly run using the shadow dom as parameter + aemComponents.forEach((aemComponentName) => { + window.addEventListener(aemComponentName, () => { + window[aemComponentName](shadowRoot); + }); + }); + + // TODO: please remove this if statement when the mega menu + // for these domains gets created in AEM + const regex = /\/(zh-hk|zh-tw)\//i; + const matches = window.location.href.match(regex); + if (matches) { + const newScriptFile = document.createElement('script'); + newScriptFile.src = '/_src/scripts/vendor/mega-menu/mega-menu.js'; + newScriptFile.defer = true; + shadowRoot.appendChild(newScriptFile); + } else { + // TODO: please keep the below code and move + // it outside the if + + // select all the scripts from contet div and + const scripts = contentDiv.querySelectorAll('script'); + scripts.forEach((script) => { + const newScript = document.createElement('script'); + newScript.src = `${Constants.PUBLIC_URL_ORIGIN}${script.getAttribute('src')}`; + newScript.defer = true; + contentDiv.appendChild(newScript); + }); + } + + shadowRoot.appendChild(contentDiv); + const body = document.querySelector('body'); + body.style.maxWidth = 'initial'; + + const header = document.querySelector('header'); + if (header) { + header.remove(); + } + + document.querySelector('body').prepend(nav); + + await Promise.allSettled(loadedLinks); + contentDiv.style.display = 'block'; + nav.classList.add('header-with-language-banner'); + + adobeMcAppendVisitorId(shadowRoot); + loginFunctionality(shadowRoot); + return; + } + const nav = document.createElement('nav'); nav.id = 'nav'; nav.innerHTML = html; @@ -446,6 +648,65 @@ export default async function decorate(block) { } } }); +} + +async function runLandingPageHeaderLogic(block) { + // fetch nav content + const navPath = getMetadata('nav') || '/nav'; + const resp = await fetch(`${navPath}.plain.html`); + const html = await resp.text(); - adobeMcAppendVisitorId('header'); + block.classList.add('lp-header', 'py-3', 'default-content-wrapper'); + const headerWrapper = block.closest('header'); + + headerWrapper.id = 'header-ferrari'; + headerWrapper.classList.add('header-spurs', 'dark'); + block.innerHTML = html; + + const lpHeader = block.closest('.lp-header'); + lpHeader.addEventListener('click', () => { + lpHeader.classList.toggle('active', !lpHeader.classList.contains('active')); + }); +} + +async function runQuizPageHeaderLogic(block) { + // fetch nav content + const navPath = getMetadata('nav') || '/nav'; + const resp = await fetch(`${navPath}.plain.html`); + const html = await resp.text(); + + block.classList.add('quiz', 'py-3', 'default-content-wrapper'); + const headerWrapper = block.closest('header'); + + headerWrapper.classList.add('dark'); + block.innerHTML = html; + + decorateIcons(block); +} + +/** + * applies header factory based on header variation + * @param {String} headerMetadata The header variation: landingpage' or none + * @param {Element} header The header element + */ +function applyHeaderFactorySetup(headerMetadata, header) { + switch (headerMetadata) { + case 'landingpage': + runLandingPageHeaderLogic(header); + break; + case 'quiz': + runQuizPageHeaderLogic(header); + break; + case 'hidden': + break; + default: + runDefaultHeaderLogic(header); + break; + } +} + +export default async function decorate(block) { + const headerMetadata = getMetadata('header-type'); + block.parentNode.classList.add(headerMetadata || 'default'); + applyHeaderFactorySetup(headerMetadata, block); } diff --git a/_src/blocks/hero-aem/hero-aem.css b/_src/blocks/hero-aem/hero-aem.css new file mode 100644 index 000000000..069f45473 --- /dev/null +++ b/_src/blocks/hero-aem/hero-aem.css @@ -0,0 +1,514 @@ +/* stylelint-disable */ +.hero-aem-container.hero-vsb { + overflow: unset !important; +} + +.hero-aem-container .hero-aem p:first-of-type:has(a) { + margin: 0; + font-size: 16px; +} +.hero-aem-container .hero-aem >p:first-of-type { + margin: 0; + margin-bottom: 20px; +} + + +.hero-aem-container .hero-aem p:first-of-type a { + margin: 0; + margin-bottom: 20px; +} +.hero-aem-container .hero-aem h1 { + color: #006DFF; + font-size: 38px; + font-weight: normal; + margin-top: 10px; + line-height: 1.1; + margin-bottom: 20px; +} +.hero-aem-container .hero-aem h2 { + margin-top: 0; + font-size: 24px; + font-weight: normal; + line-height: 1.1; +} +.hero-aem-container .hero-aem .hero-aem__mobile-image img { + border-top-left-radius: 20px; + border-top-right-radius: 20px; + width: 100%; + height: fit-content; + position: relative; + top: 6px; +} +.hero-aem-container .hero-aem .hero-aem__desktop-image { + display: none; +} +.hero-aem-container .hero-aem .hero-aem__card-text { + padding: 27px; + font-size: 20px; + background-color: #F7F7F7; + border-bottom-left-radius: 20px; + border-bottom-right-radius: 20px; +} + +.hero-aem-container .hero-aem .hero-aem__card-text picture img { + width: auto; + max-height: 60px; +} + +.hero-aem-container .hero-aem .hero-aem__card-text p:has(picture) { + text-align: center; +} + +.hero-aem-container .hero-aem .hero-aem__breadcrumb { + border-spacing: 0; + font-size: 12px; + margin-bottom: 5px; + align-self: flex-start; +} + +.hero-aem-container .hero-aem .hero-aem__breadcrumb a { + color: #202020; + text-decoration: none; +} + +.hero-aem-container .hero-aem .hero-aem__breadcrumb a:hover { + text-decoration: underline; +} + +.hero-aem-container .hero-aem p.button-container { + text-align: center; +} +.hero-aem-container .hero-aem p.button-container .button.primary { + width: 100%; +} +.hero-aem-container .hero-aem .prod-oldprice { + font-size: 16px; + text-decoration: line-through; +} +.hero-aem-container .hero-aem .prod-save { + color: #1C7928; + font-weight: bold; + font-size: 16px; + margin-left: 8px; +} +.hero-aem-container .hero-aem .prod-newprice { + font-size: 40px; + font-weight: bold; +} +.hero-aem-container .hero-aem .newprice-container { + line-height: 1; +} +.hero-aem-container .hero-aem .newprice-container sup { + position: relative; + top: -7px; +} +.hero-aem-container .aem-two-cards { + margin-top: 20px; +} +.hero-aem-container .aem-two-cards h2 { + font-size: 36px; + font-weight: bold; + line-height: 1.1; +} +.hero-aem-container .aem-two-cards_card { + border-radius: 20px; + background-color: #F7F7F7; + padding: 1.5rem; + display: flex; + flex-direction: column; + width: 100%; +} +.hero-aem-container .aem-two-cards_card .button-container { + margin-top: auto; +} +.hero-aem-container .aem-two-cards .aem-two-cards_card h2 { + color: #006DFF; + font-size: 24px; + font-weight: normal; + margin: 0; +} +.hero-aem-container .aem-two-cards .justify-space-between { + justify-content: space-between; +} + +.h-100 { + height: 100% !important; +} + +.hero-aem-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.hero-aem-container .button.primary { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.hero-aem-container .button.free-download { + color: #005ed9; + font-weight: bold; + background-color: transparent; + border: none; + margin: 0; + padding: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-decoration: none; +} + +.hero-aem-container .button.free-download:hover { + color: #0A53C5; + transform: translateX(10px); +} + +.hero-aem-container .button.free-download::after { + content: '\2192'; + width: 24px; + height: 24px; + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + margin-left: 2px; +} + +.hero-aem-container .button.free-download:hover::after { + transform: translateX(5px); +} + +/* this would ideally be the sales tax included text */ +.hero-aem__card-text p:last-child { + font-size: 14px; +} + +.hero-aem__card-text p:last-child a { + color: inherit; + margin-left: 8px; + font-weight: normal; +} + +.hero-aem-container .hero-aem p em a { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #006DFF; + background-color: transparent; + border: 2px solid #006DFF; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + transition: all .2s cubic-bezier(.4,0,.2,1); +} + +.hero-aem-container .hero-aem p em a:hover { + color: white; + background-color: #006DFF; +} + +.hero-aem-container .hero-aem p em a:active { + background-color: #0D499B; +} + +.hero-aem-container .hero-aem p strong em a { + color: black; + text-decoration: underline; +} + +.hero-aem__pill { + font-size: 14px; + font-weight: 500; + line-height: 1.1; + color: #fff; + background-color: #006DFF; + border-radius: 20px; + padding: 5px 13px; + display: inline-block; + margin-right: 10px; + margin-top: 0px; +} + +.hero-aem__underPriceText { + font-size: 14px; +} + +.hero-aem-container .aem-two-cards p a { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.hero-aem-container .aem-two-cards p:has(a) { + margin-top: auto; +} + +.hero-aem-container .aem-two-cards h2 { + font-size: 36px; + font-weight: bold; +} +.hero-aem-container .aem-two-cards .aem-two-cards_card h2 { + color: #006DFF; + font-size: 24px; + font-weight: normal; + margin: 0; +} +.hero-aem-container .row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 1.5rem; + + display: flex; + flex-wrap: wrap; + margin-top: calc(-1 * var(--bs-gutter-y)); + margin-right: calc(-.5 * var(--bs-gutter-x)); + margin-left: calc(-.5 * var(--bs-gutter-x)); +} +.hero-aem-container .row>* { + display: flex; + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x) * .5); + padding-left: calc(var(--bs-gutter-x) * .5); + margin-top: var(--bs-gutter-y); + box-sizing: border-box; +} + + +.hero-aem-container .col-12 { + flex: 0 0 auto; + width: 100%; +} + + +@media (max-width: 767px) { + .hero-aem-container.hero-vsb { + padding-bottom: 0; + } + + .hero-aem-container.hero-vsb .hero-aem { + padding: 0 15px; + } + + .hero-aem-container.hero-vsb .hero-aem__card__desktop { + max-height: unset!important; + } + + .hero-aem-container.hero-vsb .hero-aem .hero-aem__card-text { + padding: 0; + background-color: transparent; + border-radius: 20px; + } + + .hero-aem-container.hero-vsb .hero-aem p.button-container { + text-align: left; + } + + .hero-aem-container.hero-vsb .hero-aem p.button-container .button.primary { + margin: 0; + max-width: 290px; + } + + .hero-aem-container.hero-vsb .hero-aem p.button-container .button.primary span { + text-align: center; + display: block; + width: 100%; + } + + .hero-aem-container.hero-vsb .hero-aem h1 { + color: #006DFF; + font-size: 29px; + } +} + +@media (min-width: 768px) { + .hero-aem-container .hero-aem { + display: flex; + flex-wrap: wrap; + } + .hero-aem-container .hero-aem .hero-aem__mobile-image { + display: none; + } + .hero-aem-container .hero-aem .hero-aem__desktop-image { + display: block; + height: 100%; + position: relative; + } + + .hero-aem-container .hero-aem .hero-aem__desktop-image::after { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: linear-gradient(to left, rgba(247, 247, 247, 0), #F7F7F7); + } + + .hero-aem-container .hero-aem .hero-aem__desktop-image img { + height: 100%; + max-width: 800px; + width: 100%; + object-fit: cover; + border-top-right-radius: 20px; + border-bottom-right-radius: 20px; + } + .hero-aem-container .hero-aem .hero-aem__card-text { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + background-color: initial; + padding: 0; + } + + .hero-aem-container .hero-aem .hero-aem__card-text p:has(picture) { + text-align: left; + } + + .hero-aem-container .hero-aem .hero-aem__card__desktop { + background-color: #F7F7F7; + border-bottom-left-radius: 20px; + border-top-left-radius: 20px; + } + + .hero-aem-container .hero-aem .hero-aem__card__desktop--center { + display: flex; + align-items: center; + } + .hero-aem-container .hero-aem .hero-aem__card__desktop > div { + padding: 24px 0px 24px 56px; + } + .hero-aem-container .hero-aem p.button-container { + text-align: left; + display: inline-block; + } + .hero-aem-container .hero-aem p.button-container .button.primary { + width: auto; + } + + .hero-aem-container .col-md-6 { + flex: 0 0 auto; + width: 50%; + } + + .hero-aem-container .col-md-4 { + flex: 0 0 auto; + width: 33.33%; + } + + .hero-aem-container .col-md-3 { + flex: 0 0 auto; + width: 24%; + } + + .hero-aem-container .aem-two-cards h2 + p { + font-size: 18px; + } + + .hero-aem-container .hero-aem p:has(a) { + display: inline-block; + } + + .hero-aem-container .hero-aem p:has(em) { + margin-left: 10px; + } +} + +@media (max-width: 992px) { + .hero-aem-container.hero-vsb .hero-aem h1 { + font-size: 32px; + } +} + +@media (min-width: 992px) { + .hero-aem-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + .hero-aem-container .col-lg-6 { + flex: 0 0 auto; + width: 49%; + } + .hero-aem-container .col-lg-5 { + flex: 0 0 auto; + width: 41.66%; + } + .hero-aem-container .col-lg-3 { + flex: 1 0 auto; + width: 24%; + } + .hero-aem-container .col-lg-2 { + flex: 0 0 auto; + width: 16.66%; + } +} + +@media (min-width: 1200px) { + .hero-aem-container .col-lg-6 { + flex: 0 0 auto; + width: 49%; + } + + .hero-aem-container .col-lg-3 { + flex: 0 0 auto; + width: 24%; + } +} + +@media (min-width: 1200px) { + .hero-aem-container.we-container { + max-width: 1350px; + padding-left: 20px; + padding-right: 20px; + } + + .hero-aem-container .hero-aem .hero-aem__desktop-image img { + max-height: 600px; + } +} diff --git a/_src/blocks/hero-aem/hero-aem.js b/_src/blocks/hero-aem/hero-aem.js new file mode 100644 index 000000000..e4df40492 --- /dev/null +++ b/_src/blocks/hero-aem/hero-aem.js @@ -0,0 +1,205 @@ +/* eslint-disable prefer-const */ +/* eslint-disable no-undef */ +/* eslint-disable max-len */ +import { openUrlForOs } from '../../scripts/utils/utils.js'; + +let dataLayerProducts = []; +async function createPricesElement(storeOBJ, conditionText, saveText, prodName, prodUsers, prodYears, buylink, send2datalayer) { + const storeProduct = await storeOBJ.getProducts([new ProductInfo(prodName, 'consumer')]); + const storeOption = storeProduct[prodName].getOption(prodUsers, prodYears); + const price = storeOption.getPrice(); + const discountedPrice = storeOption.getDiscountedPrice(); + const discount = storeOption.getDiscount('valueWithCurrency'); + const buyLink = await storeOption.getStoreUrl(); + + let product = { + ID: storeOption.getAvangateId(), + name: storeOption.getName(), + devices: storeOption.getDevices(), + subscription: storeOption.getSubscription('months'), + version: storeOption.getSubscription('months') === 1 ? 'monthly' : 'yearly', + basePrice: storeOption.getPrice('value'), + discountValue: storeOption.getDiscount('value'), + discountRate: storeOption.getDiscount('percentage'), + currency: storeOption.getCurrency(), + priceWithTax: storeOption.getDiscountedPrice('value') || storeOption.getPrice('value'), + }; + dataLayerProducts.push(product); + + const priceElement = document.createElement('div'); + priceElement.classList.add('hero-aem__prices'); + priceElement.innerHTML = ` + ${!send2datalayer ? '

Yearly - individual

' : ''} +
+
+ ${price} + ${saveText} ${discount} +
+
+ ${discountedPrice} + ${conditionText || ''} +
+
+

Protection for 5 PCs, Macs, tablets, or smartphones.
Windows® | macOS® | Android™ | iOS®

`; + if (buylink) { + buylink.href = buyLink; + } + return priceElement; +} + +function createCardElementContainer(elements, mobileImage) { + const cardElementContainer = document.createElement('div'); + cardElementContainer.classList.add('hero-aem__card'); + + const cardElementText = document.createElement('div'); + cardElementText.classList.add('hero-aem__card-text'); + + elements.forEach((sibling) => { + if (mobileImage && sibling.contains(mobileImage)) { + cardElementContainer.appendChild(sibling); + } else { + cardElementText.appendChild(sibling); + } + }); + + cardElementContainer.appendChild(cardElementText); + + return cardElementContainer; +} + +// Function to dispatch 'shadowDomLoaded' event +function dispatchShadowDomLoadedEvent() { + const event = new CustomEvent('shadowDomLoaded', { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + window.dispatchEvent(event); +} + +export default function decorate(block, options) { + const { + product, conditionText, saveText, MacOS, Windows, Android, IOS, + alignContent, height, type, send2datalayer, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + let blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + if (type) blockParent.classList.add(type); + } + + let [richText, mainDesktopImage, richTextCard, columnsCard] = block.children; + + // Configuration for new elements + richText.classList.add('hero-aem__card__desktop', 'col-md-6'); + if (alignContent === 'center') { + richText.classList.add('hero-aem__card__desktop--center'); + } + + if (height) { + // eslint-disable-next-line array-callback-return + Array.from(block.children).map((child) => { + child.style.maxHeight = `${height}px`; + }); + } + mainDesktopImage.classList.add('col-md-6'); + mainDesktopImage.children[0].classList.add('h-100'); + + let mobileImage = block.querySelector('.hero-aem__card__desktop div > p > picture'); + if (mobileImage) { + mobileImage.classList.add('hero-aem__mobile-image'); + } else { + mobileImage = ''; + } + + // Get all the siblings after h1 + const cardElements = Array.from(block.querySelectorAll('h1 ~ *')); + // Put the siblings in a new div and append it to the block + const cardElementContainer = createCardElementContainer(cardElements, mobileImage); + + // Append the container after h1 + block.querySelector('h1').after(cardElementContainer); + + const desktopImage = block.querySelector('.hero-aem > div > div > picture'); + desktopImage.classList.add('hero-aem__desktop-image'); + + if (product && options?.store) { + const [prodName, prodUsers, prodYears] = product.split('/'); + + const buyLink = block.querySelector('a[href*="buylink"]'); + createPricesElement(options.store, conditionText, saveText, prodName, prodUsers, prodYears, buyLink, send2datalayer) + .then((pricesBox) => { + // If buyLink exists, apply styles and insert pricesBox + if (buyLink) { + buyLink.classList.add('button', 'primary'); + buyLink.parentNode.parentNode.insertBefore(pricesBox, buyLink.parentNode); + dispatchShadowDomLoadedEvent(); + return; + } + + // If buyLink does not exist, apply styles to simpleLink + const simpleLink = block.querySelector('.hero-aem__card-text a'); + if (simpleLink) { + simpleLink.classList.add('button', 'primary'); + simpleLink.parentNode.parentNode.insertBefore(pricesBox, simpleLink.parentNode); + } + + dispatchShadowDomLoadedEvent(); + }); + } else { + // If there is no product, just add the button class and dispatch the event + const simpleLink = block.querySelector('.hero-aem__card-text a'); + if (simpleLink) { + simpleLink.classList.add('button', 'primary'); + } + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + } + + let breadcrumbTable = block.querySelector('table'); + + if (breadcrumbTable && breadcrumbTable.textContent.includes('breadcrumb')) { + breadcrumbTable.classList.add('hero-aem__breadcrumb'); + // delete the first row + breadcrumbTable.deleteRow(0); + } + + let freeDownloadButton = block.querySelector('a[href*="#free-download"]'); + if (freeDownloadButton) { + freeDownloadButton.classList.add('button', 'free-download'); + openUrlForOs(MacOS, Windows, Android, IOS, freeDownloadButton); + } + + if (columnsCard) { + const columnsCardChildren = Array.from(columnsCard.children); + const cardElement = document.createElement('div'); + cardElement.classList.add('aem-two-cards'); + // Determine the appropriate column width class based on the number of cards + const columnWidthMdClass = columnsCardChildren.length === 2 ? 'col-md-6' : 'col-md-4'; + const columnWidthLgClass = columnsCardChildren.length === 2 ? 'col-lg-3' : 'col-lg-3'; + + const columnCardsHtml = columnsCardChildren.map((col) => ` +
+
+ ${col.innerHTML} +
+
`).join(''); + + cardElement.innerHTML = ` +
+
+ ${richTextCard.innerHTML} +
+ ${columnCardsHtml} +
+ `; + + block.appendChild(cardElement); + richTextCard.innerHTML = ''; + columnsCardChildren.forEach((col) => col.remove()); + } +} diff --git a/_src/blocks/hero/hero.css b/_src/blocks/hero/hero.css new file mode 100644 index 000000000..cba039d62 --- /dev/null +++ b/_src/blocks/hero/hero.css @@ -0,0 +1,1059 @@ +/* stylelint-disable no-descending-specificity */ + +/* block specific CSS goes here */ +:root { + /* hero font size */ + --hero-font-size-xxxl: 50px; + --hero-font-size-xxl: 48px; + --hero-font-size-xl: 40px; + --hero-font-size-l: 32px; + --hero-font-size-m: 22px; + --hero-font-size-s: 20px; + --hero-font-size-xs: 18px; + --hero-font-size-xxs: 16px; + --hero-font-size-xxxs: 14px; + --hero-h1-font-size: 32px; + --hero-h2-font-size: 24px; + --hero-botton-border-color: #616161; + --hero-p-color: #3c3c3c; + + /* breadcrumbs font size */ + --breadcrumb-text-color-dark: #c5c5c5; + --breadcrumb-text-color-dark-hover: #616161; + --breadcrumbs-font-size-s: 12px; +} + +main .hero { + background-color: white; + position: relative; + padding: 1em 0 2em; + min-height: 300px; +} + +main .section.bfoffer .hero { + background-color: transparent; +} + +main .section.bfoffer .hero .hero-content { + background-color: transparent; +} + +main .bfoffer .hero .hero-content p:last-of-type picture img { + display: none; +} + +/* breadcrumbs */ +main .hero .hero-content .breadcrumb { + font-weight: var(--font-weight-bold); + color: #dedede; + min-height: unset; + padding: 12px 0; + margin-bottom: 12px; +} + +main .hero .hero-content .signature { + font-size: 24px; + color: #006dff; + font-weight: bold; + margin-top: 8px; +} + +@media (min-width: 480px) { + main .hero .hero-content .signature { + margin-bottom: 12px; + } +} + +main .hero .hero-content .breadcrumb a { + font-size: var(--breadcrumbs-font-size-s); + font-weight: var(--font-weight-bold); + color: var(--breadcrumb-text-color-dark-hover); + text-decoration: none; + line-height: 1.7; + letter-spacing: .96px; +} + +main .hero .hero-content .breadcrumb a:last-child { + padding: 0; + margin: 0; + pointer-events: none; +} + +main .hero .hero-content .breadcrumb a::after { + content: "/"; + display: inline-block; + color: var(--color-dark-gray); + margin: 0 3px; + font-size: 9pt; +} + +main .hero .hero-content .breadcrumb a:hover { + color: var(--text-color); +} + +main .hero.black-background .hero-content .breadcrumb a { + color: var(--breadcrumb-text-color-dark); + text-decoration: none; +} + +main .hero.black-background .hero-content .breadcrumb a::after { + color: #dedede; +} + +main .hero.black-background .hero-content .breadcrumb a:hover { + color: var(--breadcrumb-text-color-dark-hover); +} + +/* hero */ +main .hero-container>div { + max-width: unset; +} + +main .hero-container { + padding: 0; + margin: 0 auto; +} + +main .hero-container.blue-title .hero-content>div { + width: 100%; +} + +main .hero-container.blue-title .hero-content h1 { + --tw-text-opacity: 1; + + color: rgb(0 110 255 / var(--tw-text-opacity)); +} + +main .hero-container.migration .hero-content h2 { + font-size: 22px; + font-weight: 500; + line-height: 1.25; + margin-top: 1em; + margin-bottom: 9px; +} + +main .hero-container.migration .hero-content p em { + font-size: 1.125rem; + font-style: normal; +} + +main .hero .hero-content>div { + width: 100%; +} + +main .hero-container .hero-wrapper { + padding: 0; +} + +main .hero.new2024design::after { + display: none; +} + +main .hero.black-background { + background-color: var(--dark-background-color); +} + +main .hero.new2024design * { + font-weight: normal; + font-family: "IBM Plex Sans", sans-serif; + color: white; +} + +main .hero.new2024design .hero-picture:last-of-type { + display: none; +} + +main .hero.new2024design strong { + font-weight: 600; +} + +main .hero-container.breadcrumb-hidden .breadcrumb a { + color: transparent; +} + +main .hero-container.breadcrumb-hidden .breadcrumb a::after { + color: transparent; +} + +main .hero.black-background::after { + content: none; + background-color: transparent; +} + +main .hero.comparison { + height: 600px; +} + +main .hero .hero-picture { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + +main .hero .hero-content { + display: flex; + flex-direction: column; + padding: 17px var(--body-padding) 56px; + margin: 0 auto; + position: relative; +} + +main .hero.new2024design { + max-width: 1200px; + margin: auto; +} + +main .hero.new2024design .hero-content:last-of-type { + padding: 0 2em; +} + +main .hero.new2024design .hero-picture { + padding: 0; + min-height: 0; +} + +main .hero.new2024design .hero-picture img { + padding: 0; + border-radius: 10px; + object-fit: contain; +} + +main .hero.new2024design h1 { + font-size: var(--hero-font-size-l); + margin: 0; +} + +main .hero.new2024design p { + font-size: 16px; +} + +main .hero.new2024design .hero-content.hero-content img { + padding: 0; + border-radius: 10px; + object-fit: contain; +} + +main .hero .hero-content .right-col { + display: flex; + justify-content: center; + flex-direction: column; +} + +main .hero.black-background .hero-content { + padding: 17px var(--body-padding) 56px; + display: flex; + flex-direction: column; + background: linear-gradient(90deg, #000 0%, #000 15%, #fff0 100%); +} + +main .hero.comparison .hero-content { + height: 100%; + padding: 40px; + justify-content: center; + flex-direction: column; +} + +main .hero h1 { + font-size: 2.125rem; + margin: 0 0 25px; +} + +main .affiliate .hero h1 { + color: #006DFF; + font-size: 48px; +} + + +main .hero h2 { + font-size: 18px; + color: var(--text-color); + margin: 0 0 9px; + padding: 15px 0 0; + letter-spacing: .003em; +} + +main .hero.black-background h1 { + font-size: var(--hero-h1-font-size); + margin: 0 0 25px; +} + +main .hero h2, +main .hero h4 { + padding: 0; + letter-spacing: normal; + margin: 0 0 9px; +} + +main .affiliate .hero h4{ + font-weight: 300; +} + +main .hero.black-background h1, +main .hero.black-background h2, +main .hero.black-background h4 { + color: var(--text-dark-color); +} + +main .hero.comparison h1 { + font-weight: var(--font-weight-regular); +} + +main .hero p { + color: var(--hero-p-color); + font-size: var(--hero-font-size-xxxs); + font-weight: var(--font-weight-regular); + line-height: 1.5; + display: block; + letter-spacing: .006em; + margin: 0; +} + +main .hero h1+p { + margin: 8px 0 0; + color: #616161; + font-size: var(--hero-font-size-xxxs); + line-height: 1.5; +} + +main .hero h1+p strong { + font-weight: var(--font-weight-bold); +} + +main .hero.comparison p { + font-size: 18px; + font-weight: 400; + font-stretch: normal; + font-style: normal; + line-height: 1.5; + letter-spacing: normal; + color: #fff; + margin: 24px 0 0; +} + +main .hero.black-background h1+p { + color: var(--text-dark-color); +} + +main .hero p.button-container { + margin: 0; + padding: 10px 0; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + gap: 2px; +} + +main .hero p.button-container:last-of-type { + margin: 0 0 10px; +} + +main .hero p.button-container.discount-bubble-container { + padding-top: 0; +} + +main .hero img { + object-fit: cover; + height: 100%; +} + +main .hero .hero-picture picture img { + position: absolute; + right: 0; +} + +main .hero a.button { + margin: 8px 13px 0 0; +} + +main .hero a.button.modal, +main .hero a.button.central { + padding: 0 28px 0 0; + min-width: unset; +} + +@media (min-width: 1400px) { + main .hero a.button { + min-width: 360px; + justify-content: center; + align-items: center; + } + + main .hero.ferrari h1{ + max-width: 80%; + } +} + +main .hero a.button span.button-text { + transition: all .25s cubic-bezier(.4, 0, .2, 1); + display: inline-block; + position: relative; + font-size: var(--hero-font-size-xs); + font-weight: var(--font-weight-bold); +} + +main .hero .discount-bubble { + background: #16A34A; + border-radius: 50%; + width: 72px; + height: 72px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + gap: 2px; + right: 0; + position: relative; +} + +main .hero .discount-bubble .discount-bubble-0 { + font-size: 24px; + color: #fff; + font-weight: var(--font-weight-boldest); + line-height: .8; + text-decoration: none; + padding-top: 5px; +} + +main .hero .discount-bubble .discount-bubble-1 { + font-size: 11px; + color: #fff; + line-height: 1.71; + font-weight: var(--font-weight-bold); + font-style: normal; + text-decoration: none; +} + +main .hero .wrapper-plan-discount { + margin: 0 0 10px; + display: -webkit-box; + display: flex; + flex-wrap: wrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center +} + +main .hero .hero-content ul { + margin: 20px 0 0; + padding: 0; + text-align: left; + list-style-type: none; +} + +main .hero .hero-content ul li { + font-size: var(--hero-font-size-xxs); + font-weight: var(--font-weight-regular); + letter-spacing: 0.096px; + line-height: 1.5; + color: var(--hero-p-color); + margin: 13px 0 0; + padding: 0 0 0 20px; + position: relative; + list-style: none; +} + +main .hero .hero-content ul li:first-child { + margin: 5px 0; +} + +main .hero ul li::before { + content: ""; + position: absolute; + left: 0; + top: 4px; + width: 15px; + height: 15px; + background-color: var(--background-checkmark); + border-radius: 50%; + z-index: 1; +} + +main .hero ul li::after { + content: ""; + position: absolute; + left: 5px; + top: 6px; + width: 3px; + height: 7px; + border-bottom: 2px solid var(--white-color); + border-right: 2px solid var(--white-color); + transform: rotate(45deg); + z-index: 2; +} + +main .hero ul.hero-awards { + display: flex; + flex-flow: row wrap; + align-items: center; + justify-content: flex-start; + margin: 0; + padding: 40px 0 0; + text-align: left; +} + +main .hero .hero-content ul.hero-awards li { + display: block; + min-height: 20px; + margin: 0 20px 30px 0; + padding: 0; + width: auto; +} + +main .hero ul.hero-awards li::before { + content: none; +} + +main .hero ul.hero-awards li picture img { + display: block; + height: 80px; + width: auto; +} + +main .hero-container.bigger-awards { + .hero ul.hero-awards li picture img { + height: 96px; + } +} + +main .hero .hero-awards li::after { + content: none; +} + +main .hero.pb-0 .hero-content { + padding-bottom: 0; +} + +main .v2 .hero h1 { + font-weight: var(--font-weight-regular); + font-family: var(--body-font-family); +} + +main .v2 .hero h1+p { + font-size: var(--body-font-size-s); +} + +main .v2 .hero .hero-content>div:first-of-type { + width: 100%; +} + +main .v2 .hero .hero-content>div:last-of-type img { + height: auto; + width: 360px; + position: absolute; + bottom: 0; +} + +main .v2 .hero .hero-content>div table tr { + display: flex; +} + +main .v2 .hero .hero-content>div table tr td:first-of-type { + margin-right: 2em; + width: 280px; +} + +main .v2 .hero .hero-content>div table tr td:last-of-type { + width: 465px; +} + +/* stylelint-disable-next-line selector-class-pattern */ +main .smaller_icon .hero .hero-content>div table tr td:last-of-type { + width: fit-content; +} + +main .v2 .hero .hero-content>div table tr td img { + width: 100%; + height: auto; +} + +/* stylelint-disable-next-line selector-class-pattern */ +main .smaller_icon .hero .hero-content>div table tr td:first-of-type { + width: 70px; +} + +main .hero.ferrari{ + background-color: #006DFF; +} + +main .hero.ferrari .hero-content{ + display: flex; + flex-direction: column; + color: #FFF; + padding: 20px; +} + +main .hero.ferrari .hero-content img{ + position: relative; +} + +main .hero.ferrari .breadcrumb{ + display: none; +} + +.hero-container.grey-background .hero-picture { + background-color: #f6f6f6; +} + +.hero-container.half-width-picture .hero-picture picture { + &::after { + content: ''; + position: absolute; + top: 0; + right: 25%; + bottom: 0; + left: 50%; + background: transparent linear-gradient(90deg, rgb(246 246 246 / 100%) 0%, rgb(224 224 224 / 0%) 100%); + } +} + +.hero-container.half-width-picture .hero-picture picture img { + padding-left: 50%; + position: relative; +} + +.hero-container.blue-title .h1 { + color: #006DFF; +} + +.hero-container.smaller-awards .hero ul.hero-awards { + gap: 20px; + padding: 0; + + li { + margin: 0; + } +} + +.hero-container.smaller-awards .hero ul.hero-awards li picture img { + height: 50px; +} + +main .hero-container.ferrari-migration .hero{ + background-color:#006DFF; + font-family: "IBM Plex Sans", sans-serif; + font-weight: 300; +} + +main .hero-container.ferrari-migration .hero .hero-content h1{ + color: #FFF; + line-height: 1; +} + +main .hero-container.ferrari-migration .hero .hero-content h2{ + color: #FFF; + font-weight: 300; +} + +main .hero-container.ferrari-migration .hero .hero-content p{ + color: #fff; +} + +main .hero-container.ferrari-migration .hero .hero-content .breadcrumb{ + display: none; +} + +main .hero-container.ferrari-migration .hero .hero-content a{ + font-size: 18px; + font-weight: 700; + background-color: #fff; + border-radius: 10px; + padding: 15px 10px; +} + +main .hero-container.ferrari-migration .hero .hero-content a img{ + position: relative; + bottom: -10px; + height: 87px; + margin-right: 10px; + border-radius: 5px; +} + +@media(max-width: 989px) { + main .hero.new2024design { + background-color: #006FFF; + min-height: auto; + padding: 2em 0; + } +} + +@media(max-width: 991px) { + /* tablet */ + main .hero.new2024design .breadcrumb { + display: none; + } +} + +@media(min-width: 767px) { /* tablet */ + main .hero.ferrari{ + min-height: 715px; + } + + main .hero.ferrari .hero-picture picture img{ + padding-left: 0; + object-fit:cover; + object-position: bottom; + width: 100%; + } + + main .hero.ferrari .hero-content{ + flex-flow: column; + padding: 20px; + text-align: center; + color: #fff; + max-width: 85%; + } + + main .hero.hero.ferrari .hero-content img{ + right: 0; + } + + main .hero.ferrari .hero-content > div { + display: flex; + flex-direction: column; + width: 100%; + padding: 0 20px 0 0; + + } + + main .hero.ferrari h1{ + font-size: 60px; + font-weight: 300; + align-self: center; + } + + main .hero.ferrari h1 strong{ + font-weight: 700; + } + + :root { + --hero-h1-font-size: 42px; + } + + main .hero.new2024design h1 { + font-size: var(--hero-font-size-xl); + margin: 0; + } + + main .hero.new2024design * { + color: white; + background-color: transparent; + } + + main .hero h2 { + font-size: 20px; + } + + main .hero .hero-content .breadcrumb { + min-height: 58px; + } + + main .hero .hero-content .breadcrumb a::after { + margin: 0 9px; + } + + main .hero-container.blue-title .hero-content>div { + width: 630px; + } +} + +@media (min-width: 990px) { + /* desktop */ + main .hero.new2024design .hero-content:last-of-type { + min-height: 360px; + padding: 2em; + } + + main .hero.new2024design .hero-picture { + display: block; + height: 430px; + } + + main .hero .hero-content>div.left-col { + width: 50%; + } + + main .hero .hero-content>div.right-col { + width: 50%; + padding-left: 1.25rem; + } + + main .hero h2 { + font-size: 22px; + margin-bottom: 10px; + } + + main .hero h1 { + font-size: 2.5rem; + font-weight: 700; + font-family: "IBM Plex Sans", sans-serif; + } + + main .hero .hero-picture { + position: absolute; + top: 0; + bottom: auto; + left: 0; + right: 0; + height: 100%; + } + + main .hero p { + font-size: var(--hero-font-size-xxs); + margin: 0; + } + + main .hero .hero-picture picture img { + display: block; + padding-left: 0; + } + + main .hero .hero-content { + max-width: var(--section-desktop-max-width); + min-height: unset; + padding: 1em var(--section-desktop-padding) 1em var(--section-desktop-padding); + display: flex; + flex-direction: row; + } + + main .hero.black-background .hero-content { + max-width: var(--section-desktop-max-width); + padding-left: var(--section-desktop-padding); + padding-right: var(--section-desktop-padding); + padding-top: 115px; + display: flex; + flex-direction: row; + min-height: unset; + } + + main .hero a.button.primary { + min-width: 360px; + } + + main .hero .hero-content>div { + width: 60%; + padding: 0 20px 0 0; + } + + main .hero.comparison .hero-content>div { + width: 65%; + padding: 40px 0 0; + } + + main .affiliate .hero .hero-content>div { + width: 50%; + } + + main .hero .hero-content .breadcrumb a { + line-height: 1; + letter-spacing: .96px; + } + + main .hero ul.hero-awards { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + margin: 0; + padding: 40px 0 0; + } + + main .hero ul.hero-awards li { + display: block; + min-height: 20px; + margin: 9px 20px 0 0; + padding: 0; + width: auto; + } + + /* stylelint-disable-next-line selector-class-pattern */ + main .smaller_icon .hero .hero-content>div:last-of-type img { + width: 40% !important; + } + + /* stylelint-disable-next-line selector-class-pattern */ + main .new_v2 .hero .hero-content>div:last-of-type img { + width: 60% !important; + right: 0; + } + + main .v2 .hero .hero-content>div:last-of-type img { + width: 360px; + right: -11em !important; + bottom: -3em; + } + + main .hero.ferrari .hero-content > div img{ + max-height: 225px; + max-width: 813px; + } + + main .hero-container.ferrari-migration .hero{ + min-height: 600px; + align-content: center; + } + + main .hero-container.ferrari-migration .hero .hero-content h1{ + font-size: 60px; + font-weight: 300; + } + + main .hero-container.ferrari-migration .hero .hero-content h2{ + font-size: 32px; + font-weight: 300; + margin-top: 50px; + } + + main .hero-container.ferrari-migration .hero .hero-picture img{ + width: 50%; + } +} + +@media (max-width: 1399px) { + main .hero .hero-content ul li { + font-size: var(--body-font-size-xs); + } + + main .v2 .hero h1 { + font-size: var(--heading-font-size-xxl1); + } +} + +@media (min-width: 1600px) { + /* large desktop */ + main .hero .hero-content .breadcrumb { + padding: 9px 0; + margin-bottom: 15px; + } + + main .hero h1 { + font-size: 2.5rem; + font-weight: 700; + font-family: "IBM Plex Sans", sans-serif; + } + + main .v2 .hero h1 { + font-size: var(--heading-font-size-xxl2); + } + + main .hero h2 { + color: #000; + font-size: 24px; + font-weight: 500; + line-height: 1.25; + margin-bottom: 9px; + margin-top: 10px; + } + + main .hero .discount-bubble { + width: 83px; + height: 83px; + } + + main .hero .discount-bubble .discount-bubble-0 { + font-size: 32px; + } + + main .hero .discount-bubble .discount-bubble-1 { + font-size: 14px; + } + + main .hero .hero-content { + max-width: var(--section-large-desktop-max-width); + padding-left: var(--section-large-desktop-padding); + padding-right: var(--section-large-desktop-padding); + } + + main .hero.ferrari .hero-content { + min-height: 768px; + } + + main .hero.ferrari h1 { + max-width: 60%; + } + + main .hero.black-background .hero-content { + max-width: var(--section-large-desktop-max-width); + padding-left: var(--section-large-desktop-padding); + padding-right: var(--section-large-desktop-padding); + } +} + +@media (max-width: 990px) { + main .v2 .hero h1 { + font-size: var(--heading-font-size-xl1); + } + + main .hero .hero-content>div table tr td:last-of-type { + width: 510px; + } + + main .hero .hero-content>div table tr td:first-of-type { + display: none; + } + + main .v2 .hero .hero-picture picture img { + padding-left: 0; + } + + main .v2 .hero .hero-content>div:last-of-type img { + width: 265px; + right: 0; + } +} + +@media (max-width: 768px) { + main .hero .hero-picture, + main .v2 .hero .hero-content>div:last-of-type img { + display: none; + } + + main .bfoffer main .hero { + padding-top: 3rem; + padding-bottom: 0; + } + + main .bfoffer .hero .hero-content p:last-of-type picture img { + display: block; + } + + main .v2 .hero .hero-content>div table tr td:last-of-type { + width: 100%; + } + + main .v2 .hero h1 { + font-size: var(--heading-font-size-l2); + } + + main .v2 .hero h1+p { + font-size: var(--body-font-size-xs); + } + + main .hero.ferrari .hero-picture{ + display: block; + } + + main .hero.ferrari .hero-content >div{ + text-align: center; + } + + main .hero.ferrari .hero-picture picture img{ + display: block; + position: absolute; + object-fit: cover; + padding: 0; + } + + main .hero.ferrari h1{ + font-weight: 400; + } +} + +@media (max-width: 450px) { + main .hero h1 { + font-size: var(--heading-font-size-m); + } +} \ No newline at end of file diff --git a/_src/blocks/hero/hero.js b/_src/blocks/hero/hero.js new file mode 100644 index 000000000..7ad1ffd5f --- /dev/null +++ b/_src/blocks/hero/hero.js @@ -0,0 +1,213 @@ +/* eslint-disable max-len */ +// Description: Hero block +import { + createTag, + createNanoBlock, + renderNanoBlocks, + getBrowserName, +} from '../../scripts/utils/utils.js'; + +import { UserAgent } from '../../scripts/libs/user-agent/user-agent.js'; + +function detectAndRenderOSContent(osLinkMapping, androidTemplate, iosTemplate, block) { + const button = block.querySelector('a.button'); + const dynamicTextElement = button.parentNode.nextElementSibling; + switch (UserAgent.os) { + case 'android': + button.classList.add('android'); + button.href = osLinkMapping.android.googlePlay; + dynamicTextElement.querySelectorAll('a').forEach((anchor, index) => { + anchor.textContent = osLinkMapping[androidTemplate.split(',')[index].trim()].text; + anchor.href = osLinkMapping[androidTemplate.split(',')[index].trim()].link; + }); + break; + case 'ios': + button.classList.add('ios'); + button.href = osLinkMapping.ios.appStore; + dynamicTextElement.querySelectorAll('a').forEach((anchor, index) => { + anchor.textContent = osLinkMapping[iosTemplate.split(',')[index].trim()].text; + anchor.href = osLinkMapping[iosTemplate.split(',')[index].trim()].link; + }); + break; + default: + break; + } +} + +/** + * Builds hero block and prepends to main in a new section. + * @param {Element} element The container element + */ +function buildHeroBlock(element) { + const h1 = element.querySelector('h1'); + const picture = element.querySelector('picture'); + const pictureParent = picture ? picture.parentNode : false; + // eslint-disable-next-line no-bitwise + if (h1 && picture && (h1.compareDocumentPosition(picture) & Node.DOCUMENT_POSITION_PRECEDING)) { + const section = document.querySelector('div.hero'); + const subSection = document.querySelector('div.hero div'); + subSection.classList.add('hero-content'); + + const isHomePage = window.location.pathname.split('/').filter((item) => item).length === 1; + + if (!isHomePage) { + const breadcrumb = createTag('div', { class: 'breadcrumb' }); + document.querySelector('div.hero div div:first-child').prepend(breadcrumb); + } + + const pictureEl = document.createElement('div'); + pictureEl.classList.add('hero-picture'); + pictureEl.append(picture); + section.prepend(pictureEl); + + pictureParent.remove(); + } +} + +createNanoBlock('discount', (code, label = '{label}') => { + // code = "av/3/1" + const [product, unit, year] = code.split('/'); + + const root = document.createElement('div'); + root.classList.add('discount-bubble'); + root.classList.add('await-loader'); + + // Add the required attributes to the root element + + root.setAttribute('data-store-context', ''); + root.setAttribute('data-store-id', product); + root.setAttribute('data-store-option', `${unit}-${year}`); + root.setAttribute('data-store-department', 'consumer'); + root.setAttribute('data-store-event', 'main-product-loaded'); + root.setAttribute('data-store-hide', 'no-price=discounted;type=visibility'); + root.innerHTML = ` + --% + ${label} + `; + + return root; +}); + +async function renderBubble(block) { + await renderNanoBlocks(block); + const bubble = block?.querySelector('.discount-bubble'); + if (bubble) { + const { label } = block.closest('.section').dataset; + if (label) { + bubble.innerHTML = bubble.innerHTML.replace('{label}', label); + } + + let sibling = bubble.previousElementSibling; + + while (sibling) { + if (sibling.matches('.button-container')) { + sibling.append(bubble); + break; + } + sibling = sibling.previousElementSibling; + } + } +} + +/** + * decorates hero block + * @param {Element} block The hero block element + */ +export default function decorate(block) { + const { + // this defines wether the modals automatically refresh or not in the hero banner + stopAutomaticModalRefresh, + signature, + percentProduct, + firefoxUrl, + buttonImage, + iosLink, + androidLink, + windowsLink, + macLink, + androidTemplate, + iosTemplate, + appStoreLink, + googlePlayLink, + } = block.closest('.section').dataset; + + buildHeroBlock(block); + renderBubble(block); + if (androidLink && iosLink) { + const osLinkMapping = { + android: { + link: androidLink, + googlePlay: googlePlayLink, + text: 'Android', + }, + ios: { + link: iosLink, + appStore: appStoreLink, + text: 'iOS', + }, + windows: { + link: windowsLink, + text: 'Windows', + }, + mac: { + link: macLink, + text: 'macOS', + }, + }; + detectAndRenderOSContent(osLinkMapping, androidTemplate, iosTemplate, block); + } + // Eager load images to improve LCP + [...block.querySelectorAll('img')].forEach((el) => el.setAttribute('loading', 'eager')); + + // get div class hero-content + const elementHeroContent = block.querySelector('.hero div.hero-content div'); + if (elementHeroContent !== null) { + // Select
    elements that contain a tag + const ulsWithPicture = Array.from(document.querySelectorAll('ul')).filter((ul) => ul.querySelector('picture')); + + // Apply a CSS class to each selected
      element + ulsWithPicture.forEach((ul) => ul.classList.add('hero-awards')); + + // add signature to the top of the banner + if (signature) { + const signatureElement = createTag('div', { class: 'signature' }); + signatureElement.textContent = signature; + document.querySelector('div.hero div div:first-child').prepend(signatureElement); + } + + // set the modal buttons in the hero banner to not refresh the modal on click + if (stopAutomaticModalRefresh === 'true') { + block.querySelectorAll('a.modal.button').forEach((modalButton) => { + modalButton.setAttribute('data-stop-automatic-modal-refresh', true); + }); + } + + if (buttonImage) { + const buttonImageEl = document.createElement('img'); + buttonImageEl.setAttribute('src', buttonImage); + const heroBtn = block.querySelector('a'); + heroBtn.insertAdjacentElement('afterbegin', buttonImageEl); + } + } + + // make discount dynamic + if (percentProduct) { + const [alias, variant] = percentProduct.split(','); + block.setAttribute('data-store-context', ''); + block.setAttribute('data-store-text-variable', ''); + block.setAttribute('data-store-id', alias); + block.setAttribute('data-store-department', 'consumer'); + block.setAttribute('data-store-option', variant); + block.querySelector('div').classList.add('await-loader'); + } + + // Add the await-loader class to the button that leads to the thank you page, this is an exception + // for the free antivirus page + if (block.querySelector('.button-container a[href*="/consumer/thank-you"]')) { + block.querySelector('.button-container a[href*="/consumer/thank-you"]').classList.add('await-loader'); + } + + if (firefoxUrl && getBrowserName() === 'Firefox') { + block.querySelector('a').href = firefoxUrl; + } +} diff --git a/solutions/blocks/image-columns/image-columns.css b/_src/blocks/image-columns/image-columns.css similarity index 56% rename from solutions/blocks/image-columns/image-columns.css rename to _src/blocks/image-columns/image-columns.css index 4ac2bc5cc..37389a558 100644 --- a/solutions/blocks/image-columns/image-columns.css +++ b/_src/blocks/image-columns/image-columns.css @@ -1,3 +1,5 @@ +/* stylelint-disable no-descending-specificity */ +/* stylelint-disable selector-class-pattern */ .image-columns-container ul { padding-left: 0; } @@ -35,6 +37,14 @@ justify-items: center; } +.affiliate .image-columns > div > .image-columns-img-col{ + flex: 0 1 50%; +} + +.image-columns.text_smaller > div > .image-columns-txt-col { + flex: 0 1 45%; +} + .image-columns > div > .image-columns-txt-col { flex: 0 1 45%; } @@ -89,6 +99,62 @@ margin-top: 0; } +.image-columns.trusted > div > .image-columns-txt-col { + flex: 0 1 25%; +} + +main .section.wide .image-columns img{ + height: auto; +} + +.ferrari .image-columns-wrapper{ + padding: 20px; +} + +main .image-columns.quotes > div{ + gap: 20px; +} + +main .image-columns.quotes >div > .image-columns-txt-col{ + display: flex; + flex-flow: column; + justify-content: space-between; + padding: 30px; + border-radius: 10px; + background-color: #006dff; + color: #fff; + font-size: 20px; +} + +main .image-columns.quotes > div > .image-columns-txt-col p{ + font-size: 25px; + font-weight: 300; + padding: 0; +} + +main .image-columns.quotes > div > .image-columns-img-col{ + align-items: unset; +} + +main .image-columns.quotes > div > .image-columns-img-col img{ + position: static; + height: auto; + max-width: 100%; +} + +@media (min-width: 767px){ + .image-columns.quotes > div { + flex-direction: unset; + column-gap: 58px; + align-items: center; + } + + .image-columns.quotes > div > div { + flex: 1; + order: unset; + } +} + @media (min-width: 992px) { .image-columns > div > .image-columns-txt-col h3 { margin-bottom: 26px; @@ -108,10 +174,26 @@ padding-left: var(--body-padding); } +.affiliate .image-columns > div > .image-columns-txt-col p { + padding-left: 0; + margin-top: 16px; +} + @media (min-width: 1400px) { .image-columns > div > .image-columns-txt-col p { font-size: 18px; } + + .affiliate .image-columns > div > .image-columns-txt-col p { + font-size: 16px; + padding-left: 0; + margin-top: 16px; + } + + .ferrari .image-columns-wrapper{ + padding: 0; + max-width: 1292px; + } } @media (min-width: 992px) { /* desktop */ @@ -121,9 +203,9 @@ } .image-columns > div { - align-items: flex-start; flex-direction: unset; column-gap: 58px; + align-items: center; } .image-columns > div > div { @@ -131,3 +213,9 @@ order: unset; } } + +@media (min-width: 1600px) { /* large desktop */ + .image-columns-wrapper { + max-width: var(--section-large-desktop-max-width); + } +} diff --git a/solutions/blocks/image-columns/image-columns.js b/_src/blocks/image-columns/image-columns.js similarity index 88% rename from solutions/blocks/image-columns/image-columns.js rename to _src/blocks/image-columns/image-columns.js index 7b896eb67..243fc4401 100644 --- a/solutions/blocks/image-columns/image-columns.js +++ b/_src/blocks/image-columns/image-columns.js @@ -1,3 +1,5 @@ +import { matchHeights } from '../../scripts/utils/utils.js'; + export default function decorate(block) { const cols = [...block.firstElementChild.children]; block.classList.add(`columns-${cols.length}-cols`); @@ -22,4 +24,5 @@ export default function decorate(block) { } }); }); + matchHeights(block, '.image-columns.quotes > div > div'); } diff --git a/_src/blocks/link-checker/link-checker.css b/_src/blocks/link-checker/link-checker.css new file mode 100644 index 000000000..8e5ab526f --- /dev/null +++ b/_src/blocks/link-checker/link-checker.css @@ -0,0 +1,448 @@ + +/* stylelint-disable */ +main .section.link-checker-container { + padding: 20px; + background-color: #fff; + max-width: 1350px; + padding-top: 50px; + padding-bottom: 50px; + display: flex; + justify-content: center; + overflow: visible; + font-family: 'IBM Plex Sans', Roboto, sans-serif; + + &::before { + content: ' '; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + max-height: 400px; + background-image: url("../../icons/link-checker-pattern.svg"); + background-color: #006EFF; + border-radius: 20px; + } + + &.danger { + &::before { + background-color: #3e030b; + background-image: url("../../icons/link-checker-pattern-red.svg"); + } + + .check-url { + display: none; + } + + .link-checker input[type="text"], .link-checker #inputDiv { + max-width: 100%; + border: 2px dashed #D82E21; + padding-right: 15px; + pointer-events: none; + } + + .link-checker input[type="text"] { + display: none; + } + + .link-checker #inputDiv { + display: block; + margin-bottom: 24px; + text-align: center; + } + + .link-checker .danger-image { + display: block; + } + + .link-checker h1 { + color: #EA0220; + margin-bottom: 16px; + } + + .link-checker p:not(:has(img)) { + display: none; + } + + .link-checker .buttons-container { + display: flex; + } + + .link-checker .privacy-policy { + display: none; + } + + #copy-to-clipboard { + display: none; + } + + .link-checker .result.danger { + margin-top: 0; + } + } + + &.safe { + &::before { + background-color: #3d8648; + background-image: url("../../icons/link-checker-pattern-green.svg"); + } + + .check-url { + display: none; + } + + .link-checker h1 { + margin-bottom: 16px; + } + + .link-checker input[type="text"], .link-checker #inputDiv { + max-width: 100%; + border: 2px dashed #3D8648; + padding-right: 15px; + pointer-events: none; + } + + .link-checker input[type="text"] { + display: none; + } + + .link-checker #inputDiv { + display: block; + margin-bottom: 24px; + text-align: center; + } + + .link-checker .safe-image { + display: inline-block; + } + + .link-checker p:not(:has(img)) { + display: none; + } + + .link-checker .buttons-container { + display: flex; + } + + .link-checker .privacy-policy { + display: none; + } + + #copy-to-clipboard { + display: none; + } + } + + .link-checker-wrapper { + max-width: 960px; + width: 100%; + } + + .link-checker-form { + width: 100%; + } + + .link-checker { + display: flex; + flex-direction: column; + align-items: center; + background-color: white; + border-radius: 20px; + padding: 20px; + text-align: center; + box-shadow: 0 4px 8px rgb(0 0 0 / 10%); + position: relative; + + h1 { + font-weight: bold; + font-size: 32px; + color: #006EFF; + margin-bottom: 10px; + } + + p { + font-size: 16px; + margin-bottom: 10px; + padding: 0; + } + + .safe-image { + display: none; + + img { + max-width: 196px; + } + } + + .danger-image { + display: none; + + img { + max-width: 196px; + } + } + + p:first-of-type { + margin: 0; + } + + .input-container { + display: flex; + flex-direction: column; + justify-content: center; + width: 100%; + gap: 15px; + padding-top: 10px; + } + + input[type="text"],#inputDiv { + padding: 15px; + padding-right: 35px; + font-size: 1em; + border-radius: 8px; + border: 1px solid #006EFF; + width: 100%; + margin: 0; + position: relative; + } + + #inputDiv { + text-align: left; + word-wrap: break-word; + pointer-events: none; + display: none; + } + + .input-container__container { + width: 100%; + position: relative; + } + + #copy-to-clipboard { + width: 16px; + height: 21px; + background: url("../../icons/link-checker-example.svg") no-repeat; + background-size: contain; + position: absolute; + top: 15px; + right: 15px; + cursor: pointer; + } + + .buttons-container { + justify-content: center; + margin-top: 40px; + display: none; + gap: 40px; + margin-bottom: 20px; + } + + button.check-url { + padding: 15px 40px; + cursor: pointer; + background-color: #007BFF; + color: #fff; + border: none; + border-radius: 10px; + font-weight: bold; + font-size: 1em; + } + + button.check-url:hover { + background-color: #0056b3; + } + + button.share-button, button.check-another-button { + position: relative; + cursor: pointer; + color: #007BFF; + border: none; + background-color: transparent; + font-weight: bold; + font-size: 16px; + gap:10px; + display: inline-flex; + align-items: center; + padding: 15px; + transition: all 0.3s ease-in-out; + + &:hover { + background-color: #dbf0f9; + border-radius: 8px; + } + } + + button.share-button::before { + content: url("../../icons/share.svg"); + height: 20px; + width: 20px; + display: inline-block; + } + + button.check-another-button::before { + content: url("../../icons/check.svg"); + height: 20px; + width: 20px; + display: inline-block; + } + + .share-popup { + position: absolute; + top: -85px; + min-width: fit-content; + background-color: #000; + color: #fff; + padding: 8px 12px; + border-radius: 5px; + font-size: 14px; + font-weight: bold; + box-shadow: 0 4px 6px rgb(0 0 0 / 20%); + z-index: 10; + transition: opacity 0.3s ease-in-out; + pointer-events: none; + } + + .share-popup::after { + content: ""; + position: absolute; + bottom: -6px; + left: 50%; + transform: translateX(-50%); + width: 0; + height: 0; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid #000; + } + + .button-container .share-button:hover + .share-popup, + .button-container .share-button:focus + .share-popup { + opacity: 1; + pointer-events: auto; + } + + .result { + font-size: 14px; + border-radius: 8px; + padding-bottom: 20px; + display: none; + } + + .result.safe { + background-color: #F3FEF8; + padding: 8px 30px 8px 55px; + position: relative; + text-align: left; + display: block; + + &::before { + content: ""; + background: url("../../icons/safe.svg") no-repeat; + position: absolute; + left: 14px; + top: 15%; + width: 30px; + height: 30px; + background-size: contain; + } + } + + .result.danger { + margin-top: 24px; + background-color: #FDF3F4; + padding: 8px 30px 8px 55px; + position: relative; + text-align: left; + display: block; + + &::before { + content: ""; + background: url("../../icons/bulb-pink.svg") no-repeat; + position: absolute; + left: 14px; + top: 15%; + width: 30px; + height: 30px; + background-size: contain; + } + } + + .result.danger.no-response { + text-align: left; + font-size: 14px; + margin-bottom: 19px; + + &::before { + content: ""; + background: url("../../icons/no-response.svg") no-repeat; + position: absolute; + left: 15px; + top: 20%; + width: 25px; + height: 25px; + background-size: contain; + } + } + + .privacy-policy { + margin-top: 20px; + font-size: 12px; + } + } + + @media (min-width:768px) { + margin: 0 auto; + padding-bottom: 50px; + + .link-checker{ + padding: 48px 60px 35px; + + .input-container{ + flex-direction: unset; + } + + .buttons-container{ + flex-flow: row; + margin-top: 50px; + justify-content: center; + } + + button.check-url { + white-space: nowrap; + } + + .share-popup{ + top: -40px; + max-width: unset; + white-space: nowrap; + } + + p { + font-size: 20px; + margin-bottom: 20px; + padding: 0; + } + + h1 { + font-size: 40px; + margin-bottom: 40px; + } + + .result { + font-size: 16px; + border-radius: 8px; + padding-bottom: 30px; + } + + .privacy-policy { + font-size: 14px; + } + } + } + + @media (min-width: 991px) { + .link-checker { + padding: 48px 160px 35px; + } + } +} \ No newline at end of file diff --git a/_src/blocks/link-checker/link-checker.js b/_src/blocks/link-checker/link-checker.js new file mode 100644 index 000000000..03d01b06d --- /dev/null +++ b/_src/blocks/link-checker/link-checker.js @@ -0,0 +1,279 @@ +import { + AdobeDataLayerService, + PageLoadedEvent, + PageLoadStartedEvent, + UserDetectedEvent, +} from '../../scripts/libs/data-layer.js'; +import { + BotPrevention, +} from '../../scripts/utils/bot-prevention.js'; + +class StatusMessageFactory { + static createMessage(status, url) { + let urlObject = url; + // Ensure the URL has a protocol + if (!/^https?:\/\//i.test(url)) { + urlObject = `http://${url}`; + } + urlObject = new URL(urlObject); + + // Ensure the URL contains www + if (!urlObject.hostname.startsWith('www.')) { + urlObject.hostname = `www.${urlObject.hostname}`; + } + + const messages = { + 1: { text: 'The link is safe with no signs of harmful activity. You can go ahead and keep staying cautious online.', className: 'result safe', status: 'safe' }, + 2: { text: 'We haven\'t found any suspicious activity with this link. However, to stay safe going forward, make sure to use reliable security software and scan your system regularly.', className: 'result safe', status: 'so_far_so_good_1' }, + 3: { text: `This link looks safe, but the domain '${urlObject.hostname}' has been connected to harmful links in the past. To stay protected, check any other links from this domain using our tool and keep your security software updated.`, className: 'result safe', status: 'so_far_so_good_2' }, + 4: { text: 'This link is dangerous and can compromise your personal information or harm your device. Do not click it, and ensure your security software is up-to-date to stay protected from threats.', className: 'result danger', status: 'malware & phishing' }, + 5: { text: 'This link is known to distribute malware. Accessing it may harm your device, steal your data, or allow unauthorized access. Stay away from the site and ensure your security software is active.', className: 'result danger', status: 'malware' }, + 6: { text: 'This URL is linked to a server used to command and control malware on infected devices. Don’t click the link and make sure your security software is up to date to keep your device safe.', className: 'result danger', status: 'c&c' }, + 7: { text: 'This link is a threat, exposing you to malicious ads and phishing attempts that can steal your information and damage your device. Do not interact with it, and ensure your security software is updated.', className: 'result danger', status: 'malvertising & fraud & phishing' }, + 8: { text: 'This link directs to a fraudulent site intended to trick users and steal sensitive data. Stay away from the site and ensure your security software is active.', className: 'result danger', status: 'fraud' }, + 9: { text: 'This link leads to a phishing site designed to steal personal information like passwords or financial data. Stay away from the site and ensure your security software is active.', className: 'result danger', status: 'phishing' }, + 10: { text: 'This link is connected to harmful ads that could affect your device and expose your personal data, such as your passwords, credit card information, email addresses, or browsing history. Avoid clicking on it and keep your security software updated to stay safe.', className: 'result danger', status: 'malvertising' }, + 11: { text: 'This link is associated with apps that could slow down your device or compromise your privacy. It’s best to avoid the site and make sure your security settings are active.', className: 'result danger', status: 'pua' }, + 12: { text: 'This link is designed to look like a trusted site using tricky characters. Don’t click the link and make sure your security software is updated to protect your device.', className: 'result danger', status: 'homograph' }, + 13: { text: 'This URL is linked to cryptocurrency mining activities, which may use your device\'s resources without your consent. Avoid visiting the site and ensure your security protections are in place.', className: 'result danger', status: 'miner' }, + 14: { text: 'This URL is linked to crypto mining activity, which could use your device\'s resources if accessed. It’s recommended not to click the link and ensure your security software is up to date.', className: 'result danger', status: 'miner-server' }, + 15: { text: 'This link has been identified in spam emails, which often contain malicious content. Avoid clicking on it, as it may lead to harmful sites or scams. Ensure your security measures are in place.', className: 'result danger', status: 'spam' }, + 16: { text: 'This URL is likely to contain malware, posing a significant threat. It\'s strongly advised to avoid accessing it and ensure your security protections are active and up to date.', className: 'result danger', status: 'malware-hd' }, + 17: { text: 'This link appears suspicious and may not be trustworthy. It’s best to avoid accessing it. Keep your security software active and steer clear of the site.', className: 'result danger', status: 'untrusted' }, + 18: { text: 'This link is unsafe and could harm your device or steal your personal information. Avoid clicking on it and keep your security software updated to stay safe.', className: 'result danger', status: 'malicious' }, + other: { text: 'This link is unsafe and could harm your device or steal your personal information. Avoid clicking on it and keep your security software updated to stay safe.', className: 'result danger', status: 'other' }, + }; + return messages[status] || { text: `Status: ${status}`, className: 'result warning' }; + } +} + +function changeTexts(block, result) { + switch (result.status) { + case 'safe': + block.querySelector('h1').textContent = "You're safe"; + break; + case 'so_far_so_good_1': + block.querySelector('h1').textContent = 'So far, so good'; + break; + case 'so_far_so_good_2': + block.querySelector('h1').textContent = 'So far, so good'; + break; + default: + block.querySelector('h1').textContent = 'Definitely Don’t Go There'; + break; + } +} + +const isValidUrl = (urlString) => { + const urlPattern = new RegExp('^(https?:\\/\\/)?' // validate protocol + + '((([a-z\\d]([a-z\\d-_]*[a-z\\d])*)\\.)+[a-z]{2,}|' // validate domain name + + '((\\d{1,3}\\.){3}\\d{1,3}))' // validate OR ip (v4) address + + '(\\:\\d+)?(\\/[-a-z\\d%_.~+@]*)*' // validate port and path + + '(\\?[;&a-z\\d%\\/_@.~+=-]*)?' // validate query string + + '(\\#[-a-z\\d_]*)?$', 'i'); // validate fragment locator + return urlPattern.test(urlString); +}; + +async function checkLink(block, input, result) { + const url = input.value.trim(); + if (!url || !isValidUrl(url)) { + result.textContent = 'Please enter a valid URL'; + result.className = 'result danger'; + return; + } + + input.closest('.input-container').classList.add('loader-circle'); + let response = await fetch('https://eu.nimbus.bitdefender.net/tools/link-checker', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Nimbus-ClientID': '81b10964-a3c1-44f6-b5ac-7eac82db3ab1', + }, + body: JSON.stringify({ url }), + }); + + if (response.status === 401) { + const challengeData = await response.json(); + const solvedChallenge = await BotPrevention.solveChallange(challengeData); + response = await fetch('https://eu.nimbus.bitdefender.net/tools/link-checker', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Nimbus-ClientID': '81b10964-a3c1-44f6-b5ac-7eac82db3ab1', + }, + // eslint-disable-next-line max-len + body: JSON.stringify({ url, pow_challenge: challengeData.pow_challenge, pow_solution: solvedChallenge.nonces }), + }); + } + + if (!response.ok) { + result.innerHTML = ` + Something went wrong
      + The system encountered an error while trying to check the link you provided. Please try again in a few minutes.`; + result.className = 'result danger no-response'; + input.closest('.input-container').classList.remove('loader-circle'); + return; + } + + const data = await response.json(); + const { status } = data; + const message = StatusMessageFactory.createMessage(status, url); + result.textContent = message.text; + result.className = message.className; + block.closest('.section').classList.add(message.className.split(' ')[1]); + input.setAttribute('disabled', ''); + document.getElementById('inputDiv').textContent = url; + + changeTexts(block, message); + input.closest('.input-container').classList.remove('loader-circle'); + + const newObject = await new PageLoadStartedEvent(); + newObject.page.info.name = `${newObject.page.info.name}:${message.status}`; + AdobeDataLayerService.push(newObject); + AdobeDataLayerService.push(await new UserDetectedEvent()); + AdobeDataLayerService.push(new PageLoadedEvent()); +} + +async function resetChecker(block) { + const classesToRemove = ['danger', 'safe']; + const section = block.closest('.section'); + + // Iterate over the classes and remove them from the section + classesToRemove.forEach((className) => { + if (section.classList.contains(className)) { + section.classList.remove(className); + } + }); + + // Reset the input and result elements + const input = block.querySelector('#link-checker-input'); + const result = block.querySelector('.result'); + const h1 = block.querySelector('h1'); + input.removeAttribute('disabled'); + input.value = ''; + result.className = 'result'; + h1.textContent = 'Is This Link Really Safe?'; + + const newObject = await new PageLoadStartedEvent(); + AdobeDataLayerService.push(newObject); + AdobeDataLayerService.push(await new UserDetectedEvent()); + AdobeDataLayerService.push(new PageLoadedEvent()); +} + +function createSharePopup(element) { + element.style.maxWidth = `${element.offsetWidth}px`; + element.style.maxHeight = `${element.offsetHeight}px`; + const sharePopup = document.createElement('div'); + sharePopup.classList.add('share-popup'); + element.insertAdjacentElement('beforeend', sharePopup); + return sharePopup; +} + +function copyToClipboard(block, caller, popupText) { + const copyText = window.location.href; + + // Copy the text inside the text field + navigator.clipboard.writeText(copyText); + const buttonsContainer = block.querySelector('.buttons-container'); + if (buttonsContainer) { + const sharePopup = block.querySelector('.share-popup') || createSharePopup(caller); + sharePopup.textContent = `${popupText}`; + const translateXValue = Math.abs((sharePopup.offsetWidth - caller.offsetWidth) / 2); + sharePopup.style = `transform:translateX(-${translateXValue}px); opacity: 1`; + setTimeout(() => { + sharePopup.style = `transform:translateX(-${translateXValue}px); opacity:0;`; + }, 2000); + } +} + +export default function decorate(block) { + const { clipboardText } = block.closest('.section').dataset; + + const privacyPolicyDiv = block.querySelector(':scope > div:nth-child(3)'); + privacyPolicyDiv.classList.add('privacy-policy'); + + const formContainer = document.createElement('div'); + formContainer.classList.add('link-checker-form'); + + const inputContainer = document.createElement('div'); + inputContainer.classList.add('input-container'); + formContainer.appendChild(inputContainer); + + const input = document.createElement('input'); + input.type = 'text'; + input.placeholder = 'example-url.com'; + input.id = 'link-checker-input'; + + const copyElement = document.createElement('span'); + copyElement.id = 'copy-to-clipboard'; + + const inputDiv = document.createElement('p'); + inputDiv.setAttribute('id', 'inputDiv'); + + const divContainer = document.createElement('div'); + divContainer.className = 'input-container__container'; + divContainer.appendChild(input); + block.prepend(inputDiv); + divContainer.appendChild(copyElement); + + inputContainer.appendChild(divContainer); + + copyElement.addEventListener('click', async () => { + try { + const text = await navigator.clipboard.readText(); + input.value += text; + } catch (error) { + // continue regardless of error + } + }); + + const button = document.createElement('button'); + button.textContent = 'Check URL'; + button.classList.add('check-url'); + inputContainer.appendChild(button); + + const result = document.createElement('div'); + result.className = 'result'; + formContainer.appendChild(result); + + const buttonsContainer = document.createElement('div'); + buttonsContainer.classList.add('buttons-container'); + + const shareButton = document.createElement('button'); + shareButton.innerHTML = 'Share Link Checker'; + shareButton.classList.add('share-button'); + + const checkAnother = document.createElement('button'); + checkAnother.innerHTML = 'Check Another Link'; + checkAnother.classList.add('check-another-button'); + + buttonsContainer.appendChild(shareButton); + buttonsContainer.appendChild(checkAnother); + + formContainer.appendChild(buttonsContainer); + block.querySelectorAll(':scope > div')[1].replaceWith(formContainer); + const [safeImage, dangerImage] = block.querySelectorAll('picture'); + safeImage.classList.add('safe-image'); + dangerImage.classList.add('danger-image'); + + button.addEventListener('click', () => checkLink(block, input, result)); + checkAnother.addEventListener('click', () => resetChecker(block)); + shareButton.addEventListener('click', (e) => { + e.preventDefault(); + copyToClipboard(block, shareButton, clipboardText); + }); + + // if the text is cleared, do not display any error + input.addEventListener('input', () => { + const url = input.value.trim(); + // If the input is cleared, reset the result text and class + if (url === '') { + result.textContent = ''; + result.className = ''; + } + }); + input.addEventListener('paste', () => { + result.textContent = ''; + result.className = ''; + }); +} diff --git a/_src/blocks/marquee/marquee.css b/_src/blocks/marquee/marquee.css new file mode 100644 index 000000000..01ed88103 --- /dev/null +++ b/_src/blocks/marquee/marquee.css @@ -0,0 +1,69 @@ +/* stylelint-disable custom-property-pattern */ +.marquee-container.section { + padding: 0; + position: relative; + overflow: unset; + max-width: 100%; +} + +.marquee-container .marquee.block { + height: 150px; + display: flex; + flex-direction: column; + width: 100%; +} + +.marquee-container .title { + font: normal normal 600 12px/15px "IBM Plex Sans", sans-serif; + letter-spacing: 0; +} + +.marquee-container .marquee-content { + display: flex; + animation: scrolling 10s linear infinite; + + --translateX: 100%; + + height: 100%; +} + +.marquee-container .marquee-item { + flex: 0 0 85px; + margin: 0 20px; +} + +.marquee-container .marquee-item img { + display: block; + width: 100%; + object-fit: contain; +} + +.marquee-container .outer-wrapper { + width: 100%; + height: 100%; + overflow: hidden; +} + +@keyframes scrolling { + from { transform: translateX(0); } + to { transform: translateX(calc(var(--translateX) * -1)); } +} + +@media (min-width: 990px) { + .marquee-container .marquee.block { + height: 120px; + } + + .marquee-container .title { + font: normal normal 600 18px/23px "IBM Plex Sans", sans-serif; + position: absolute; + top: -45px; + z-index: 1; + } +} + +@media (min-width: 1600px) { + .marquee-container .title { + margin-left: -25px + } +} diff --git a/_src/blocks/marquee/marquee.js b/_src/blocks/marquee/marquee.js new file mode 100644 index 000000000..ce8f1b073 --- /dev/null +++ b/_src/blocks/marquee/marquee.js @@ -0,0 +1,82 @@ +import { debounce, getDatasetFromSection, isView } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const defaultBackgroundColor = '#004299'; + const SLIDE_SIZE_ENUM = { + MOBILE: 85 + 20 * 2, + TABLET_UP: 85 + 20 * 2, + }; + + const SPEED_ANIMATION = 0.6; + + const [title, ...initialSlideList] = [...block.children]; + + function getCurrentViewportSlideSize() { + return isView('mobile') ? SLIDE_SIZE_ENUM.MOBILE : SLIDE_SIZE_ENUM.TABLET_UP; + } + function calculateSlideListBasedOnScreenWidth() { + const result = { + duplicatedSlides: null, + slidesToShift: null, + }; + + const currentViewportSlideSize = getCurrentViewportSlideSize(); + const clientWidth = window.innerWidth; + const spaceToFillMore = clientWidth - initialSlideList.length * currentViewportSlideSize; // ok + if (spaceToFillMore < 0) { + result.duplicatedSlides = initialSlideList.concat(initialSlideList); + result.slidesToShift = initialSlideList.length; + + return result; + } + // fill space + const fullWidthSlidesToFill = parseInt(spaceToFillMore / currentViewportSlideSize, 10); + const hasPartialSlideToFill = clientWidth % currentViewportSlideSize !== 0; + + result.duplicatedSlides = Array(fullWidthSlidesToFill) + .fill(initialSlideList).flatMap((slide) => slide); + + if (!hasPartialSlideToFill) { + result.duplicatedSlides = result.duplicatedSlides.concat(result.duplicatedSlides); + result.slidesToShift = result.duplicatedSlides.length; + + return result; + } + + // need to apply the patch here + result.duplicatedSlides = result.duplicatedSlides.concat(initialSlideList); + result.slidesToShift = result.duplicatedSlides.length; + result.duplicatedSlides = result.duplicatedSlides.concat(result.duplicatedSlides); + + return result; + } + + function updateTranslation(slidesToShift) { + const content = block.querySelector('.marquee-content'); + content.style.animationDuration = `${slidesToShift / SPEED_ANIMATION}s`; + content.style.setProperty('--translateX', `${getCurrentViewportSlideSize() * slidesToShift}px`); + } + + function render() { + const blockDataset = getDatasetFromSection(block); + const { background_color: backgroundColor } = blockDataset; + block.style.background = backgroundColor || defaultBackgroundColor; + + const { duplicatedSlides, slidesToShift } = calculateSlideListBasedOnScreenWidth(); + + block.innerHTML = ` +
      ${title.textContent}
      +
      +
      + ${duplicatedSlides.map((slide) => `
      ${slide.querySelector('picture').outerHTML}
      `).join('')} +
      +
      + `; + + updateTranslation(slidesToShift); + } + + render(); + + window.addEventListener('resize', debounce(render, 250)); +} diff --git a/_src/blocks/mbox-canvas/mbox-canvas.css b/_src/blocks/mbox-canvas/mbox-canvas.css new file mode 100644 index 000000000..370174cf0 --- /dev/null +++ b/_src/blocks/mbox-canvas/mbox-canvas.css @@ -0,0 +1,16 @@ +.mbox-canvas-container { + display: flex; + justify-content: center; + + .mbox-canvas-wrapper { + height: 512px; + width: 770px; + display: flex; + justify-content: center; + align-items: center; + + .mbox-canvas { + width: 100%; + } + } +} \ No newline at end of file diff --git a/_src/blocks/mbox-canvas/mbox-canvas.js b/_src/blocks/mbox-canvas/mbox-canvas.js new file mode 100644 index 000000000..bdef838ff --- /dev/null +++ b/_src/blocks/mbox-canvas/mbox-canvas.js @@ -0,0 +1,58 @@ +import { Target } from '../../scripts/libs/data-layer.js'; +import { decorateMain, detectModalButtons } from '../../scripts/scripts.js'; +import { loadBlocks } from '../../scripts/lib-franklin.js'; + +function decorateHTMLOffer(aemHeaderHtml) { + const newHtml = document.createElement('div'); + newHtml.innerHTML = aemHeaderHtml; + decorateMain(newHtml); + detectModalButtons(newHtml); + + return newHtml; +} + +function createOfferParameters() { + const parameters = {}; + const urlParams = new URLSearchParams(window.location.search); + const feature = urlParams.get('feature'); + const language = urlParams.get('lang'); + urlParams.forEach((value) => { + if (value === feature) { + parameters.feature = feature; + } + if (value === language) { + parameters.lang = language; + } + }); + + return parameters; +} + +export default async function decorate(block) { + const { + // eslint-disable-next-line no-unused-vars + mboxName, + } = block.closest('.section').dataset; + + const parameters = createOfferParameters(); + block.innerHTML += ` +
      + +
      + `; + block.classList.add('loader-circle'); + const offer = await Target.getOffers([{ + name: mboxName, + parameters, + }]); + const page = await fetch(`${offer[mboxName].content.offer}`); + const offerHtml = await page.text(); + const decoratedOfferHtml = decorateHTMLOffer(offerHtml); + block.querySelector('.canvas-content').innerHTML = decoratedOfferHtml.innerHTML; + await loadBlocks(block.querySelector('.canvas-content')); + + // make all the links from the canvas open in a new browser window + block.querySelectorAll('a').forEach((link) => { + link.setAttribute('target', '_blank'); + }); +} diff --git a/_src/blocks/money-back/money-back.css b/_src/blocks/money-back/money-back.css new file mode 100644 index 000000000..9ac08a531 --- /dev/null +++ b/_src/blocks/money-back/money-back.css @@ -0,0 +1,289 @@ +.money-back-wrapper { + text-align: center; +} + +@media (min-width: 992px) { /* desktop */ + .money-back-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +@media (min-width: 1600px) { /* large desktop */ + .money-back-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +.money-back.block { + background-color: #EDF9FF; + border-radius: 20px; +} + +.creator-money-back .money-back.block { + background-color: transparent; +} + +.money-back.block.background-white { + background-color: white; +} + +.money-back-container h3 { + font: normal normal bold 32px/37px var(--body-font-family); + text-align: center; + margin-bottom: 56px; +} + +.money-back-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.money-back-container .icon svg { + width: auto; + height: 32px; + padding-right: 2px; +} + +.creator-money-back.money-back-container .icon svg { + width: auto; + height: 60px; + padding-right: 2px; +} + +.money-back > ul { + list-style: none; + margin: 0; + padding: 0; + display: inline-block; + } + +.creator-money-back .money-back > ul { + display: flex; + } + +.money-back > ul > li { + display: inline-block; + padding: 8px; + margin: 0 37px; + text-align: center; + width: 268px; + vertical-align: top; + font: normal normal normal 14px/16px var(--body-font-family); + } + + .creator-money-back .money-back > ul > li { + background: #F5F5F7; + border-radius: 20px; + padding: 60px 68px; + flex: 1; + width: auto; + text-align: left; + margin: 0 30px; + vertical-align: top; + font: normal normal normal 20px/23px Arial, sans-serif; + } + + .money-back > ul > li h6 { + font: normal normal bold 18px/16px var(--body-font-family); + } + + .money-back > ul > li p { + font: normal normal normal 14px/16px var(--body-font-family); + } + + .creator-money-back .money-back > ul > li h4 { + font: normal normal bold 32px/38px "IBM Plex Sans", sans-serif; + } + + .creator-money-back .money-back > ul > li p { + font: normal normal normal 20px/26px Arial, sans-serif; + } + + .money-back > ul > li p:first-of-type { + margin-bottom: 0; + } + + .creator-money-back .money-back > ul > li p:first-of-type { + margin: 0; + } + + .money-back > ul > li a { + font: normal normal normal 14px/16px var(--body-font-family); + margin-bottom: 0; + margin-top: 20px; + text-decoration: none; + color: #006EFF; + display: block; + } + + .money-back > ul > li strong { + display: inline-block; + font: normal normal bold 18px/16px var(--body-font-family); + padding-bottom: 11px; + } + + .money-back .default-content-wrapper { + text-align: center; + } + + .money-back > ul > li p.button-container { + margin-top: 0; + } + + .money-back a.button { + font: normal normal normal 14px/16px var(--body-font-family); + margin-top: 20px; + padding: 0; + background: transparent; + border: none; + color: #006EFF; + } + + .money-back a.button:hover { + text-decoration: underline; + color: #006EFF; + background: transparent; + } + + .money-back a.button span.button-text { + transition: none; + } + + .money-back a.button:hover span.button-text { + transform: none; + } + + .money-back a.button::after { + content: ''; + width: 0; + height: 0; + margin: 0; + transition: none; + } + + .creator-money-back .money-back > ul > li a { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px / 24px Roboto, sans-serif; + color: white; + } + + .creator-money-back .money-back > ul > li a:hover { + color: white; + background-color: var(--button-background-color); + text-decoration: none; + } + + .creator-money-back .money-back a.button span.button-text { + transition: transform .2s cubic-bezier(.4,0,.2,1); + } + + .creator-money-back .money-back > ul > li a.button:hover span.button-text { + transform: translate(-10px, 0); + } + + .creator-money-back .money-back > ul > li a:active { + color: white; + background-color: var(--button-background-color); + border: 0; + } + + .creator-money-back .money-back a.button::after { + content: ''; + width: 24px; + height: 24px; + margin-left: -10px; + transition: all .2s cubic-bezier(.4,0,.2,1); + } + + .money-back .icon { + height: 32px; + margin-bottom: 9px; + fill: #006EFF; + display: flex; + } + + .creator-money-back .money-back .icon { + height: 60px; + margin-bottom: 23px; + fill: #006DFF; + display: flex; + } + + .money-back img { + height: 55px; + margin-bottom: 9px; + fill: #006EFF; + } + + .creator-money-back .money-back img { + height: 60px; + fill: #006df7; + display: flex; + } + +@media (max-width: 991px) { /* mobile/tablet */ + .money-back-wrapper { + padding: var(--body-padding); + } + + .money-back > ul { + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + grid-gap: 14px; + flex-direction: column; + } + + .money-back > ul > li { + margin: 0; + } + + .money-back-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (max-width: 1259px) { + .creator-money-back .money-back > ul > li { + margin-bottom: 40px; + } +} + +@media (min-width: 1200px) { + .money-back-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .money-back-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (max-width: 991px) { + .creator-money-back .money-back > ul > li { + margin: 0; + padding: 24px; + } + + .creator-money-back .money-back > ul > li p.button-container { + text-align: center; + } +} \ No newline at end of file diff --git a/_src/blocks/money-back/money-back.js b/_src/blocks/money-back/money-back.js new file mode 100644 index 000000000..e4fbe7ba9 --- /dev/null +++ b/_src/blocks/money-back/money-back.js @@ -0,0 +1,23 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + const ul = document.createElement('ul'); + [...block.children].forEach((row) => { + const li = document.createElement('li'); + li.innerHTML = row.innerHTML; + + ul.append(li); + }); + + block.textContent = ''; + block.append(ul); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/new-prod-boxes/new-prod-boxes.css b/_src/blocks/new-prod-boxes/new-prod-boxes.css new file mode 100644 index 000000000..1ed9cc7cc --- /dev/null +++ b/_src/blocks/new-prod-boxes/new-prod-boxes.css @@ -0,0 +1,771 @@ +/* stylelint-disable */ +.new-prod-boxes-container.remove-first > div.default-content-wrapper:first-of-type { + display: none; +} + +.creators .new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box { + border: 1px solid #ECECEC; +} + +.creators .new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .undeBuyLink { + text-align: center; + font-weight: bold; +} + +.new-prod-boxes-container { + padding-bottom: 0; + font-family: 'Arial', sans-serif; + margin: clamp(10px, 25px, 15px) 0; +} + +.new-prod-boxes-container div.default-content-wrapper:last-of-type { + padding: 0; +} + +.new-prod-boxes-container div.default-content-wrapper:last-of-type * { + font: normal normal normal 12px/14px Arial; + color: black; +} + +.new-prod-boxes-container div.default-content-wrapper:last-of-type a { + text-decoration: underline; +} + +.new-prod-boxes-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.new-prod-boxes-container .default-content-wrapper p:has(> a) { + text-align: center; + font-size: 16px; +} + +.new-prod-boxes-container .default-content-wrapper p:has(> a) a { + text-align: center; + font-size: 16px; + color: #005ed9; + text-decoration: none; +} + +.new-prod-boxes-container .default-content-wrapper p:has(> a) a:hover { + color: #00439c; + text-decoration: underline; +} + +.new-prod-boxes-container .default-content-wrapper h2 { + text-align: center; + font-size: 32px; + line-height: 37px; + max-width: 550px; + margin: auto; + margin-bottom: 20px; +} + +.new-prod-boxes-container .new-prod-boxes { + margin: 0 auto; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box { + flex: 1; + max-width: 410px; + margin: 8px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box { + position: relative; + height: 100%; + background-color: #F6F6F6; + border-radius: 20px; + padding: 25px; + margin: 0 auto; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .greenTag2 { + height: 30px; + max-width: 350px; + width: 86%; + font-family: Arial, sans-serif; + color: white; + text-align: center; + background-color: #1C7928; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + padding-top: 7px; + position: absolute; + top: -39px; + left: 7%; + box-sizing: content-box; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box h4 { + font-weight: bold; + font-size: 22px; + line-height: 26px; + font-family: Arial, sans-serif; + margin-top: 0; + margin-bottom: 4px; + width: 80% +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box h4 a { + transition: all 0.5s ease; + color: #000; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box h4 a:hover { + text-decoration: none; + transition: all 0.5s ease; + color: #005ed9; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTagsWrapper { + display: flex; + gap: 5px; + flex-wrap: wrap; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTag { + font-size: var(--body-font-size-xs); + font-family: Arial, sans-serif; + color: white; + text-align: center; + background-color: #026DFF; + display: inline-block; + border-radius: 20px; + padding: 6px 16px; + margin-bottom: 10px; + display: flex; + gap: 5px; + height: fit-content; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTag .icon { + width: fit-content; + height: auto; + display: flex; + align-items: center; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTag div { + display: flex; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTag img { + height: 14px; + margin-right: 5px; + margin-top: -5px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .subtitle { + font-size: clamp(10px, 14px, 14px); + font-family: Arial, sans-serif; + margin-bottom: 0; + line-height: 1.25; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .subtitle.fixed_height { + min-height: 80px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box hr { + border: 1px solid #D1D1D1; + margin: 10px 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box hr:first-of-type { + margin-bottom: 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box hr:last-of-type { + margin-bottom: 10px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .save_price_box { + display: flex; + justify-content: left; + align-items: center; + margin-bottom: 8px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .save_price_box .prod-oldprice { + font-size: var(--heading-font-size-xs); + line-height: var(--heading-font-size-xs); + text-decoration: line-through; + margin-right: 10px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .save_price_box .prod-percent { + font-size: 13px; + line-height: 15px; + color: white; + background-color: #68BA68; + border-radius: 11px; + padding: 4px 10px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .prices_box { + display: flex; + justify-content: left; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .prices_box .prod-newprice { + font-size: var(--heading-font-size-xl); + line-height: var(--heading-font-size-xl); +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .prices_box sup { + margin: 15px 0 0 5px; + font-size: var(--heading-font-size-s); + line-height: var(--heading-font-size-s); +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .billed { + font-size: 12px; + font-family: Arial, sans-serif; + line-height: 13px; + margin: 7px 0 20px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .buy-btn a.red-buy-button { + width: 100%; + text-transform: none; + font-size: 14px; + line-height: 14px; + font-weight: 500 !important; + padding: 10px 1% !important; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .undeBuyLink { + font-size: 12px; + font-family: Arial, sans-serif; + line-height: 13px; + margin: 10px 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists { + font-family: Arial, sans-serif; + color: transparent; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists p { + margin: 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists u { + font-size: var(--body-font-size-xs); + text-decoration: none; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul { + margin-top: -5px; + padding: 0; + color: black; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li { + padding-left: 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:first-of-type { + font-size: 16px; + line-height: 18px; + text-decoration: none; + list-style-type: none; + font-weight: bold; + font-family: Arial, sans-serif; + margin-bottom: 0.5rem; +} + +.new-prod-boxes-container { + .new-prod-boxes { + .prod_box { + .inner_prod_box { + .benefitsLists { + ul { + &.checkmark-list { + background-color: #E7E7E7; + padding: 13px 48px 16px 10px; + filter: grayscale(1); + border-radius: 8px; + margin-bottom: 8px; + li { + &:first-of-type { + display: flex; + align-items: center; + font-size: 14px; + + .checkmark { + appearance: none; + -webkit-appearance: none; + display: grid; + width: 18px; + height: 18px; + padding: 0; + border: 1px solid #FFFFFF; + border-radius: 1px; + margin-right: 16px; + transition: cubic-bezier(0.075, 0.82, 0.165, 1); + + &::after { + content: ""; + width: 18px; + height: 18px; + clip-path: polygon(17% 54%, 28% 43%, 38% 54%, 70% 22%, 81% 33%, 38% 75%, 17% 54%); + transform: scale(0); + background-color: white; + } + &:checked { + background: #016DFF 0% 0% no-repeat padding-box; + -webkit-box-shadow: 0px 0px 5px 0px rgba(1,109,255,1); + -moz-box-shadow: 0px 0px 5px 0px rgba(1,109,255,1); + box-shadow: 0px 0px 5px 0px rgba(1,109,255,1); + } + &:checked::after { + transform: scale(1); + } + } + } + } + + &.checked { + filter: grayscale(0); + background-color: #EAF5EC; + } + } + } + } + + .add-on-product { + transition: all 0.4s; + } + } + } + } +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:first-of-type.has_arrow::before { + content: ""; + margin: 0 5px 20px 0; + background: url("https://bitdefender.com/pages/icons/arrow-left-blue.png") no-repeat center transparent; + width: 20px; + height: 20px; + background-size: 15px 12px; + float: left; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:first-of-type.has_arrow_right .arrow-right { + background: url("https://bitdefender.com/icons/arrow-right-solid.svg") no-repeat center transparent; + width: 20px; + height: 20px; + background-size: 15px 12px; + position: relative; + top: 4px; + display: inline-flex; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) { + font-size: 14px; + line-height: 17px; + margin-bottom: 8px; + list-style-type: none; + background: url("https://bitdefender.com/icons/circle-check-sharp-solid.svg") top 2px left no-repeat transparent; + padding-left: 22px; + background-size: 13px; + position: relative; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) .white-pill-content { + position: absolute; + background-color: white; + padding: 10px; + border-radius: 10px; + margin-bottom: 28px; + left: 0; + bottom: 0; + z-index: 1; + font-size: 12px; + box-shadow: 4px 4px 7px -8px #000; + display: none; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) .white-pill-content::before { + content: ""; + position: absolute; + left: 17px; + bottom: -20px; + border-width: 10px; + border-style: solid; + border-color: white transparent transparent; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type):hover .white-pill-content{ + display: block; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) u { + font-size: 14px; + font-weight: bold; + color: white; + border-radius: 20px; + padding: 2px 21px 2px 7px; + background: url("https://bitdefender.com/pages/images/icons/individual.svg") center right 6px no-repeat #026DFF; + background-size: auto 12px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul:nth-of-type(2) { + min-height: 5em; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box.hasGreenTag { + margin-top: 45px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box.hasGreenTag .inner_prod_box { + box-shadow: 0 3px 7px 0 #C1C1C1; +} + +.new-prod-boxes-container .prod-oldprice { + font-size: 16px; + text-decoration: line-through; +} + +.new-prod-boxes-container .prod-save { + color: #1C7928; + font-weight: bold; +} + +.new-prod-boxes-container .prod-newprice { + font-size: 40px; + font-weight: bold; +} +.new-prod-boxes-container .prod-newprice .per-m { + font-size: 20px; + top: -12px; +} +.new-prod-boxes-container .newprice-container { + line-height: 1; +} + +.new-prod-boxes-container .newprice-container sup { + position: relative; + top: -20px; +} + +.new-prod-boxes-container .button.primary { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: block; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.new-prod-boxes-container .new-prod-boxes.smallerbuttons .button.primary { + display: inline-block; + min-width: 144px; +} + +.new-prod-boxes-container .new-prod-boxes.smallerbuttons .button.secondary { + display: inline-block; + min-width: 144px; +} + +.new-prod-boxes-container .button.primary.no-arrow::after { + content: none; +} + +.new-prod-boxes-container .button.secondary.no-arrow::after { + content: none; +} + +.new-prod-boxes-container .button.primary:hover { + color: white; + background-color: #B10304; + border-color: #B10304; +} + +.new-prod-boxes-container .button.primary:active { + background-color: #920A0A; + border-color: #920A0A; +} + +.new-prod-boxes-container p em a { + font-size: 16px !important; + font-style: normal !important; + font-weight: 500 !important; + -webkit-font-smoothing: antialiased !important; + display: block !important; + align-items: center !important; + box-sizing: border-box !important; + text-decoration: none !important; + padding: 10px 26px 8px 28px !important; + text-align: center !important; + cursor: pointer !important; + color: #006EFF !important; + background-color: transparent !important; + border: 2px solid #006EFF !important; + white-space: nowrap !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + border-radius: 8px !important; + height: fit-content !important; +} + +.new-prod-boxes-container .new-prod-boxes.smallerbuttons p em a { + display: inline-block; + min-width: 144px; +} + +.new-prod-boxes-container p em a:hover { + color: white !important; + background-color: #006DFF !important; +} + +.new-prod-boxes-container p em a:active { + background-color: #0D499B !important; +} + +.new-prod-boxes-container .icon { + width: 12px; + height: 14px; + margin: 0 0 0 0; +} + +.new-prod-boxes-container .icon svg { + width: 12px; + height: 14px; + margin-left: -1px; + fill: #fff; +} + +.new-prod-boxes-container .blue-pill { + background-color: #026DFF; + padding: 2.5px 6.7px; + border-radius: 20px; + color: white; + font-style: normal; + font-size: 11px; + letter-spacing: 0px; + font-weight: bold; + display: inline-flex; + justify-content: center; +} + +.new-prod-boxes-container .blue-pill .icon { + position: relative; + top: 1.5px; + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; +} + +.new-prod-boxes-container .blue-pill svg { + width: 9px; + height: 9px; +} + +.switchBox { + text-align: center; + padding-bottom: 35px; +} + +.switchBox .switch { + position: relative; + display: inline-flex; + align-items: center; + width: 302px; + height: 44px; + background-color: #016DFF; + border-radius: 22px; +} + +.switchBox .switch input { + display: none; +} + +.switchBox .slider { + position: absolute; + content: ""; + height: 40px; + width: 150px; + left: 2px; + bottom: 2px; + background-color: white; + border-radius: 20px; + transition: all 0.4s; +} + +.switchBox .switch input:checked + .slider { + transform: translateX(149px); +} + +.switchBox .label { + font-family: Arial, Helvetica, sans-serif; + width: 50%; + text-align: center; + font-weight: bold; + line-height: 34px; + font-size: 16px; + color: white; + transition: color 0.4s; + cursor: pointer; +} + +.switchBox .label.right { + z-index: 10; + color: black; +} + +.switchBox .label.left { + z-index: 10; +} + +.switchBox .switch input:checked ~ .label.right { + transition: color 0.4s; + color: white !important; +} + +.switchBox .switch input ~ .label .icon { + position: relative; + margin-right: 10px; + top: 2px; +} + +.switchBox .switch input ~ .label .icon svg { + width: 14px; + height: 16px; +} + +.switchBox .switch input ~ .label.right .icon svg { + fill: #026DFF; +} + +.switchBox .switch input:checked ~ .label.right .icon svg { + fill: white; +} + +.switchBox .switch input:checked ~ .label.left { + transition: color 0.4s; + color: black; +} + +.switchBox .switch input:checked ~ .label.left .icon svg { + fill: #026DFF; +} + +.prod-box.individual-box { + transition: all 0.4s; +} + +.prod_box.family-box { + display: none; + transition: all 0.4s; +} + +.hero-aem__prices { + margin-top: 20px; +} + +.plan-switcher { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; + font-weight: bold; + margin-bottom: 24px; + margin-top: 16px; +} + +.plan-switcher input[type=radio] { + position: relative; + display: none; + opacity: 0; + width: auto; +} + +.plan-switcher .radio-label { + margin-right: 8px; + cursor: pointer; +} + +.plan-switcher .radio-label::before { + content: ""; + background: #f4f4f4; + color: #006DFF; + border-radius: 100%; + border: 2px solid #006DFF; + display: inline-block; + width: 1.2rem; + height: 1.2rem; + position: relative; + margin-right: 9px; + vertical-align: top; + cursor: pointer; + text-align: center; + transition: all 250ms ease; +} + +.plan-switcher input[type=radio]:checked+.radio-label:before { + background-color: #3197EE; + box-shadow: inset 0 0 0 4px #f4f4f4; +} + +.plan-switcher input[type=radio]:focus+.radio-label:before { + outline: none; + border-color: #3197EE; +} + +@media (min-width: 768px) { + .creators .new-prod-boxes-container .new-prod-boxes { + padding-bottom: 10px; + } + + .new-prod-boxes-container .new-prod-boxes { + flex-direction: row; + padding-bottom: 60px; + align-items: initial; + margin-top: 37px; + } + + .new-prod-boxes-container .new-prod-boxes .prod_box.hasGreenTag { + margin: 8px; + } +} + +@media (min-width: 992px) { + .new-prod-boxes-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .new-prod-boxes-container.we-container { + padding-left: 20px; + padding-right: 20px; + } +} \ No newline at end of file diff --git a/_src/blocks/new-prod-boxes/new-prod-boxes.js b/_src/blocks/new-prod-boxes/new-prod-boxes.js new file mode 100644 index 000000000..fc6218738 --- /dev/null +++ b/_src/blocks/new-prod-boxes/new-prod-boxes.js @@ -0,0 +1,459 @@ +/* eslint-disable prefer-const */ +/* eslint-disable no-undef */ +/* eslint-disable max-len */ +import { + matchHeights, formatPrice, + checkIfConsumerPage, +} from '../../scripts/utils/utils.js'; +import { Store, ProductInfo } from '../../scripts/libs/store/index.js'; + +function setDiscountedPriceAttribute(type, hideDecimals, prodName) { + let priceAttribute = 'discounted||full'; + + if (type === 'monthly') { + priceAttribute = hideDecimals === 'true' ? 'discounted-monthly-no-decimal||full-monthly' : 'discounted-monthly||full-monthly'; + if (prodName.endsWith('m')) { + priceAttribute = hideDecimals === 'true' ? 'discounted-no-decimal||full' : 'discounted||full'; + } + } + + return priceAttribute; +} + +async function updateProductPrice(prodName, saveText, buyLinkSelector = null, billed = null, type = null, hideDecimals = null, perPrice = '') { + let priceElement = document.createElement('div'); + let newPrice = document.createElement('span'); + + let priceAttribute = setDiscountedPriceAttribute(type, hideDecimals, prodName); + newPrice.setAttribute('data-store-price', priceAttribute); + + let oldPrice = 'data-store-price="full"'; + let billedPrice = 'data-store-price="discounted||full"'; + if (hideDecimals === 'true') { + oldPrice = 'data-store-price="full-no-decimal"'; + billedPrice = 'data-store-price="discounted-no-decimal||full-no-decimal"'; + } + + priceElement.innerHTML = ` +
      +
      + + ${saveText} +
      +
      + ${newPrice.outerHTML} ${perPrice && `${perPrice.textContent.replace('0', '')}`} +
      + ${billed ? `
      ${billed.innerHTML.replace('0', ``)}
      ` : ''} + ${buyLinkSelector.innerText} +
      `; + return priceElement; +} + +function createPlanSwitcher(radioButtons, cardNumber, prodsNames, prodsUsers, prodsYears, variant = 'default') { + const planSwitcher = document.createElement('div'); + planSwitcher.classList.add('plan-switcher'); + planSwitcher.classList.toggle('addon', variant === 'addon'); + + let radioArray = ['yearly', 'monthly', '3-rd-button']; + if (variant === 'addon') { + radioArray = ['add-on-yearly', 'add-on-monthly']; + } + + Array.from(radioButtons.children).forEach((radio, idx) => { + let radioText = radio.textContent; + let plan = radioArray[idx]; + let productName = prodsNames[idx]; + let prodUser = prodsUsers[idx]; + let prodYear = prodsYears[idx]; + let checked = idx === 0 ? 'checked' : ''; + let defaultCheck = radio.textContent.match(/\[checked\]/g); + if (defaultCheck) { + radioText = radioText.replace('[checked]', ''); + checked = 'checked'; + } + + if (productName) { + planSwitcher.innerHTML += ` + +
      + `; + } + }); + + return planSwitcher; +} + +function createFeatureList(featuresSet) { + return Array.from(featuresSet).map((table) => { + const trList = Array.from(table.querySelectorAll('tr')); + const liString = trList.map((tr) => { + const tdList = Array.from(tr.querySelectorAll('td')); + let firstTdContent = tdList.length > 0 && tdList[0].textContent.trim() !== '' ? `${tdList[0].innerHTML}` : ''; + const secondTdContent = tdList.length > 1 && tdList[1].textContent.trim() !== '' ? `${tdList[1].innerHTML}` : ''; + let liClass = ''; + + if (firstTdContent === '') { + liClass += 'd-none'; + } + + if (firstTdContent.indexOf('?pill') !== -1) { + let pillText = firstTdContent.match(/\?pill (\w+)/); + let iconElement = firstTdContent.match(/(.*?)<\/span>/); + if (pillText) { + let icon = tdList[0].querySelector('span'); + const pillElement = document.createElement('span'); + pillElement.classList.add('blue-pill'); + pillElement.innerHTML = `${pillText[1]}${iconElement ? iconElement[0] : ''}`; + firstTdContent = firstTdContent.replace(pillText[0], `${pillElement.outerHTML}`); + if (icon) { + let count = 0; + firstTdContent = firstTdContent.replace(new RegExp(icon.outerHTML, 'g'), (match) => { + count += 1; + return (count === 2) ? '' : match; + }); + } + } + } + + if (firstTdContent.indexOf('<pill') !== -1 || firstTdContent.indexOf('<') !== -1) { + liClass += ' has_arrow'; + firstTdContent = firstTdContent.replace('<-', ''); + } + + if (firstTdContent.indexOf('->') !== -1 || firstTdContent.indexOf('>') !== -1) { + liClass += ' has_arrow_right'; + firstTdContent = firstTdContent.replace('->', ''); + } + + if (firstTdContent.indexOf('[checkmark]') !== -1) { + firstTdContent = firstTdContent.replace('[checkmark]', ''); + } + + if (firstTdContent.indexOf('[add-on]') !== -1) { + firstTdContent = firstTdContent.replace('[add-on]', ''); + } + + if (firstTdContent.indexOf('<<add-on-newprice>>') !== -1) { + firstTdContent = firstTdContent.replace('<<add-on-newprice>>', ''); + } + if (firstTdContent.indexOf('<<add-on-oldprice>>') !== -1) { + firstTdContent = firstTdContent.replace('<<add-on-oldprice>>', ''); + } + + if (firstTdContent.indexOf('<<add-on-percent-save>>') !== -1) { + firstTdContent = firstTdContent.replace('<<add-on-percent-save>>', ''); + } + + if (firstTdContent.indexOf('[[') !== -1) { + firstTdContent = firstTdContent.replace('[[', '('); + } + + if (firstTdContent.indexOf(']]') !== -1) { + firstTdContent = firstTdContent.replace(']]', ')'); + } + + const liContent = `
    • ${firstTdContent}${secondTdContent}
    • `; + return liContent; + }).join(' '); + + return `
        ${liString}
      `; + }); +} + +// Function to check if content contains [add-on] text +function checkAddOn(featuresSet) { + let addOn = false; + // eslint-disable-next-line array-callback-return + Array.from(featuresSet).map((table) => { + const trList = Array.from(table.querySelectorAll('tr')); + // eslint-disable-next-line array-callback-return + trList.map((tr) => { + const tdList = Array.from(tr.querySelectorAll('td')); + let firstTdContent = tdList.length > 0 && tdList[0].textContent.trim() !== '' ? `${tdList[0].innerHTML}` : ''; + if (firstTdContent.indexOf('[add-on]') !== -1) { + addOn = true; + } + }); + }); + + return addOn; +} + +export default async function decorate(block) { + const { + // eslint-disable-next-line no-unused-vars + products, familyProducts, monthlyProducts, pid, mainProduct, + addOnProducts, addOnMonthlyProducts, type, hideDecimals, thirdRadioButtonProducts, saveText, addonProductName, + } = block.closest('.section').dataset; + + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + + let defaultContentWrapperElements = block.closest('.section').querySelector('.default-content-wrapper')?.children; + let individualSwitchText; + let familySwitchText; + if (defaultContentWrapperElements) { + [...defaultContentWrapperElements].forEach((element) => { + if (element.innerHTML.includes('<slider-1 ')) { + element.innerHTML = element.innerHTML.replace('<slider-1 ', ''); + individualSwitchText = element.innerHTML; + element.remove(); + } + if (element.innerHTML.includes('<slider-2 ')) { + element.innerHTML = element.innerHTML.replace('<slider-2 ', ''); + familySwitchText = element.innerHTML; + element.remove(); + } + }); + } + + let switchBox = document.createElement('div'); + if (individualSwitchText && familySwitchText) { + switchBox.classList.add('switchBox'); + switchBox.innerHTML = ` + + `; + + // Get the checkbox inside the switchBox + let switchCheckbox = switchBox.querySelector('#switchCheckbox'); + // Add an event listener to the checkbox + switchCheckbox.addEventListener('change', () => { + if (switchCheckbox.checked) { + let familyBoxes = block.querySelectorAll('.family-box'); + familyBoxes.forEach((box) => { + box.style.display = 'block'; + }); + + let individualBoxes = block.querySelectorAll('.individual-box'); + individualBoxes.forEach((box) => { + box.style.display = 'none'; + }); + } else { + let familyBoxes = block.querySelectorAll('.family-box'); + familyBoxes.forEach((box) => { + box.style.display = 'none'; + }); + + let individualBoxes = block.querySelectorAll('.individual-box'); + individualBoxes.forEach((box) => { + box.style.display = 'block'; + }); + } + }); + } + + const productsAsList = products && products.replaceAll(' ', '').split(','); + const familyProductsAsList = familyProducts && familyProducts.replaceAll(' ', '').split(','); + const combinedProducts = productsAsList.concat(familyProductsAsList); + const monthlyPricesAsList = monthlyProducts && monthlyProducts.replaceAll(' ', '').split(','); + const thirdRadioButtonProductsAsList = thirdRadioButtonProducts && thirdRadioButtonProducts.replaceAll(' ', '').split(','); + const addOnProductsAsList = addOnProducts && addOnProducts.replaceAll(' ', '').split(','); + const addOnProductsInitial = addOnProductsAsList && addOnProductsAsList.slice(0, productsAsList.length); + const addOnMonthlyProductsAsList = addOnMonthlyProducts && addOnMonthlyProducts.replaceAll(' ', '').split(','); + const billedTexts = []; + + if (combinedProducts.length) { + [...block.children].map(async (prod, key) => { + const mainTable = prod.querySelector('tbody'); + const [greenTag, title, blueTag, subtitle, radioButtons, perPrice, billed, buyLink, undeBuyLink, benefitsLists, billed2, buyLink2] = [...mainTable.querySelectorAll(':scope > tr')]; + const [prodName, prodUsers, prodYears] = combinedProducts[key].split('/'); + const [prodMonthlyName, prodMonthlyUsers, prodMonthlyYears] = monthlyPricesAsList ? monthlyPricesAsList[key].split('/') : []; + const [prodThirdRadioButtonName, prodThirdRadioButtonUsers, prodThirdRadioButtonYears] = thirdRadioButtonProductsAsList ? thirdRadioButtonProductsAsList[key].split('/') : []; + const [addOnProdName, addOnProdUsers, addOnProdYears] = addOnProductsAsList ? addOnProductsAsList[key].split('/') : []; + const [addOnProdMonthlyName, addOnProdMonthlyUsers, addOnProdMonthlyYears] = addOnMonthlyProductsAsList ? addOnMonthlyProductsAsList[key].split('/') : []; + const featuresSet = benefitsLists.querySelectorAll('table'); + const featureList = createFeatureList(featuresSet); + billedTexts.push(billed); + let addOn = checkAddOn(featuresSet); + let buyLinkSelector = prod.querySelector('a[href*="#buylink"]'); + if (buyLinkSelector) { + buyLinkSelector.classList.add('button', 'primary'); + } else { + buyLinkSelector = buyLink.querySelector('a'); + } + + let planSwitcher = document.createElement('div'); + if (radioButtons && monthlyProducts) { + let prodsNames = [prodName, prodMonthlyName, prodThirdRadioButtonName]; + let prodsUsers = [prodUsers, prodMonthlyUsers, prodThirdRadioButtonUsers]; + let prodsYears = [prodYears, prodMonthlyYears, prodThirdRadioButtonYears]; + planSwitcher = createPlanSwitcher(radioButtons, key, prodsNames, prodsUsers, prodsYears); + } + let planSwitcher2 = document.createElement('div'); + if (addOn && addOnProducts && addOnMonthlyProducts) { + let prodsNames = [addOnProdName, addOnProdMonthlyName]; + let prodsUsers = [addOnProdUsers, addOnProdMonthlyUsers]; + let prodsYears = [addOnProdYears, addOnProdMonthlyYears]; + planSwitcher2 = createPlanSwitcher(radioButtons, key, prodsNames, prodsUsers, prodsYears, 'addon'); + } + + let newBlueTag = document.createElement('div'); + if (blueTag) { + let blueTagChildren = blueTag.children; + blueTagChildren = Array.from(blueTagChildren); + blueTagChildren.forEach((child) => { + // create a different blueTag element + newBlueTag.innerHTML += `
      ${child.innerHTML}
      `; + }); + } + + let secondButton = buyLink?.querySelectorAll('a')[1]; + if (secondButton) { + secondButton.classList.add('button', 'secondary', 'no-arrow'); + } + + // default billedText will be the first one + let billedText = billed?.children[0]; + // default billed text changes if we have the [checked] flag in the planSwitcher + Array.from(radioButtons?.children)?.forEach((radio, idx) => { + if (radio.textContent.match(/\[checked\]/g)) { + billedText = billed.children[idx]; + } + }); + + // set the store event on the component + let storeEvent = 'main-product-loaded'; + if (checkIfConsumerPage()) { + storeEvent = 'product-loaded'; + } + + const prodBox = document.createElement('div'); + prodBox.innerHTML = ` +
      prodEntry.includes(prodName)) ? `data-store-event="${storeEvent}"` : ''}> +
      + ${greenTag.innerText.trim() ? `
      ${greenTag.innerText.trim()}
      ` : ''} + ${title.innerText.trim() ? `

      ${title.innerHTML}

      ` : ''} + +
      ${newBlueTag.innerText.trim() ? `${newBlueTag.innerHTML.trim()}` : ''}
      + ${subtitle.innerText.trim() ? `

      ${subtitle.innerText.trim()}

      ` : ''} +
      + ${radioButtons ? planSwitcher.outerHTML : ''} +
      + ${secondButton ? secondButton.outerHTML : ''} + ${undeBuyLink.innerText.trim() ? `` : ''} +
      + ${benefitsLists.innerText.trim() ? `
      ${featureList}
      ` : ''} + +
      +
      `; + block.children[key].outerHTML = prodBox.innerHTML; + let priceBox = await updateProductPrice(prodName, saveText, buyLink.querySelector('a'), billedText, type, hideDecimals, perPrice); + block.children[key].querySelector('.hero-aem__prices').appendChild(priceBox); + + let addOnPriceBox; + if (addOn && addOnProducts) { + addOnPriceBox = await updateProductPrice(addOnProdName, saveText, buyLink2.querySelector('a'), billed2, type, hideDecimals, perPrice); + block.children[key].querySelector('.hero-aem__prices__addon').appendChild(addOnPriceBox); + } + + let checkmark = block.children[key].querySelector('.checkmark'); + if (checkmark) { + let checkmarkList = checkmark.closest('ul'); + checkmarkList.classList.add('checkmark-list'); + + let li = checkmark.closest('li'); + li.removeChild(checkmark); + + let checkBox = document.createElement('input'); + checkBox.setAttribute('type', 'checkbox'); + checkBox.classList.add('checkmark'); + + // rewrite the list element so flexbox can work + let newLi = document.createElement('li'); + newLi.innerHTML = ` + ${checkBox.outerHTML} +
      ${li.innerHTML}
      `; + li.replaceWith(newLi); + + block.children[key].querySelector('.add-on-product').setAttribute('data-store-context', ''); + block.children[key].querySelector('.add-on-product').setAttribute('data-store-id', addOnProdName); + block.children[key].querySelector('.add-on-product').setAttribute('data-store-option', `${addOnProdUsers}-${addOnProdYears}`); + block.children[key].querySelector('.add-on-product').setAttribute('data-store-department', 'consumer'); + if (addOnProductsInitial && addOnProductsInitial.some((prodEntry) => prodEntry.includes(addOnProdName))) { + block.children[key].querySelector('.add-on-product').setAttribute('data-store-event', storeEvent); + } + + let productObject = await Store.getProducts([new ProductInfo(prodName), new ProductInfo(addOnProdName)]); + let product = productObject[prodName]; + let addOnProduct = productObject[addOnProdName]; + if (addOnProduct) { + let addOnCost = addOnProduct.getOption(addOnProdUsers, addOnProdYears).getDiscountedPrice('value') - product.getOption(prodUsers, prodYears).getDiscountedPrice('value'); + addOnCost = formatPrice(addOnCost, product.getCurrency()); + + let addOnNewPrice = newLi.querySelector('.add-on-newprice'); + addOnNewPrice.textContent = addOnCost; + let addOnOldPrice = newLi.querySelector('.add-on-oldprice'); + addOnOldPrice.textContent = formatPrice(addOnProduct.getOption(addOnProdUsers, addOnProdYears).getPrice('value'), addOnProduct.getCurrency()); + let addOnPercentSave = newLi.querySelector('.add-on-percent-save'); + addOnPercentSave.textContent = `${addOnPriceBox.querySelector('.prod-save').textContent} ${addOnProduct.getOption(addOnProdUsers, addOnProdYears).getDiscount('percentageWithProcent')}`; + + let checkBoxSelector = newLi.querySelector('.checkmark'); + checkBoxSelector.addEventListener('change', () => { + if (checkBoxSelector.checked) { + checkmarkList.classList.add('checked'); + block.children[key].querySelector('.add-on-product').style.display = 'block'; + } else { + checkmarkList.classList.remove('checked'); + block.children[key].querySelector('.add-on-product').style.display = 'none'; + } + }); + } + } + }); + } + + if (individualSwitchText && familySwitchText) { + block.parentNode.insertBefore(switchBox, block); + } + + // handling of the billedText below the price + [...block.children].forEach((box, key) => { + box.querySelectorAll('.plan-switcher input').forEach((radio, idx) => { + radio.addEventListener('change', () => { + let billedText = billedTexts[key].children[idx]?.innerHTML; + if (billedText) { + box.querySelector('.billed').innerHTML = billedText; + } + }); + }); + }); + + window.hj = window.hj || function initHotjar(...args) { + (hj.q = hj.q || []).push(...args); + }; + hj('event', 'new-prod-boxes'); + + // decorate icons if the component is being called from www-websites + const isInLandingPages = window.location.href.includes('www-landing-pages') || window.location.href.includes('bitdefender.com/pages'); + if (!isInLandingPages) { + const { decorateIcons } = await import('../../scripts/lib-franklin.js'); + decorateIcons(block.closest('.section')); + } + + if (blockParent.classList.contains('same-height-lists')) { + const prodCard = block.querySelector('.prod_box'); + const featureLists = prodCard?.querySelectorAll('ul'); + featureLists?.forEach((list, idx) => { + matchHeights(block, `ul:nth-of-type(${idx + 1})`); + }); + } + + matchHeights(block, '.subtitle'); + matchHeights(block, 'h2'); + matchHeights(block, 'h4'); + matchHeights(block, '.plan-switcher'); + matchHeights(block, '.blueTagsWrapper'); +} diff --git a/_src/blocks/news-bar/news-bar.css b/_src/blocks/news-bar/news-bar.css new file mode 100644 index 000000000..6e9216116 --- /dev/null +++ b/_src/blocks/news-bar/news-bar.css @@ -0,0 +1,72 @@ +.news-bar { + text-align: center; + justify-content: center; + background-color: #006EFF; + color: white; + display: flex; + line-height: 1.2; + padding: 8px 0; + align-items: center; + + a { + color: white; + transition: all 1s ease; + text-decoration: underline; + } + + transition: all 1s ease; +} + +.news-bar-container.solutions { + .news-bar { + font-size: 16px; + line-height: 21px; + } + + a { + display: block; + font-size: 14px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 7px 29px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + width: fit-content; + margin: 10px auto 0; + transition: all 0.1s ease; + } + + a:hover { + background-color: #D80000; + border: 2px solid #D80000; + } +} + +@media screen and (min-width: 991px) { + .news-bar { + height: 44px; + } + + .news-bar-container.solutions { + .news-bar { + height: 61px; + + a { + display: inline-flex; + margin: 0 0 0 29px; + } + } + } +} \ No newline at end of file diff --git a/_src/blocks/news-bar/news-bar.js b/_src/blocks/news-bar/news-bar.js new file mode 100644 index 000000000..150c7db14 --- /dev/null +++ b/_src/blocks/news-bar/news-bar.js @@ -0,0 +1,37 @@ +export default function decorate(block, options) { + const { + solutions, hideDate, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + } + + if (solutions) { + block.closest('.section').classList.add('solutions'); + } + + const blockParent = block.closest('.section'); + setTimeout(() => { + const elementLink = block.querySelector('a'); + block.style.backgroundColor = '#E4F2FF'; + block.style.color = '#006EFF'; + if (elementLink && !blockParent.classList.contains('solutions')) elementLink.style.color = '#006EFF'; + }, 2000); + + if (hideDate) { + const currentDate = new Date(); + const hiddenDate = new Date(hideDate); + if (hiddenDate < currentDate) { + block.style.display = 'none'; + } + } + + setTimeout(() => { + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, + }); + }, 700); +} diff --git a/_src/blocks/particle-background/particle-background.css b/_src/blocks/particle-background/particle-background.css new file mode 100644 index 000000000..64a6ece6a --- /dev/null +++ b/_src/blocks/particle-background/particle-background.css @@ -0,0 +1,62 @@ + +.particle-background { + position: relative; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 400px; + border-radius: 25px; + color: white; + text-align: center; + overflow: hidden; + max-width: 1332px; + z-index: 1; + margin: 48px 0; +} + +.we-container { + margin: 0 auto; + padding: 0 20px; + max-width: 1330px; + position: relative; +} + +.particle-background #ts-particles { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + padding: 0; + margin: 0; +} + +.particle-background h2 { + font-size: clamp(1.5rem, 5vw, 2.5rem); + margin: 0 auto; + line-height: 42px; + max-width: 500px; +} + +.particle-background p { + font-size: 18px; +} + +.particle-background div { + z-index: 1; + padding: 24px; +} + +@media (max-width: 768px) { + .particle-background h2 { + line-height: 30px; + } +} + +@media (min-width: 1200px) { + .particle-background-container.we-container { + max-width: 1330px; + padding: 0 20px; + } +} diff --git a/_src/blocks/particle-background/particle-background.js b/_src/blocks/particle-background/particle-background.js new file mode 100644 index 000000000..46ff22281 --- /dev/null +++ b/_src/blocks/particle-background/particle-background.js @@ -0,0 +1,145 @@ +/* eslint-disable prefer-const */ +/* eslint-disable camelcase */ +// import * as all from '../../scripts/vendor/tsparticles/tsparticles.bundle.min.js'; +// eslint-disable-next-line no-unused-vars +// import { +// loadScript, +// } from '../../scripts/lib-franklin.js'; + +// eslint-disable-next-line no-unused-vars +function debounce(func, wait) { + let timeout; + return function executedFunction(...args) { + const later = () => { + clearTimeout(timeout); + func(...args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; +} + +function isView(viewport) { + const element = document.querySelectorAll(`[data-${viewport}-detector]`)[0]; + return !!(element && getComputedStyle(element).display !== 'none'); +} + +let tsParticles; +let loadAll; + +async function init(block, aemOptions) { + // eslint-disable-next-line import/no-unresolved + tsParticles = (await import('https://cdn.jsdelivr.net/npm/@tsparticles/engine@3.7.1/+esm')).tsParticles; + // eslint-disable-next-line import/no-unresolved + loadAll = (await import('https://cdn.jsdelivr.net/npm/@tsparticles/all@3.7.1/+esm')).loadAll; + const particleIdSelector = 'ts-particles'; + + const particleDiv = document.createElement('div'); + particleDiv.setAttribute('id', particleIdSelector); + + if (aemOptions) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } else { + block.parentElement.classList.add('we-container'); + } + + const particleBackground = block.parentElement.querySelector('.particle-background'); + particleBackground.prepend(particleDiv); + + async function loadParticles(options) { + await loadAll(tsParticles); + + await tsParticles.load({ id: particleIdSelector, options }); + // await loadScript('../../../_src/scripts/vendor/tsparticles/tsparticles.bundle.min.js'); + // await window.tsParticles.load({ id: particleIdSelector, options }); + // let script = document.createElement('script'); + // script.src = 'https://cdn.jsdelivr.net/npm/tsparticles@3.3.0/tsparticles.bundle.min.js'; + // script.src = 'https://dlp-fixes--www-websites--bitdefender.hlx.page/_src/scripts/vendor/tsparticles/tsparticles.bundle.min.js'; + // script.src = '../../../_src/scripts/vendor/tsparticles/tsparticles.bundle.min.js'; + // block.appendChild(script); + // script.onload = () => { + // console.log('tsParticles loaded'); + // // console.log('tsParticles', tsParticles); + // (async () => { + // // await loadFull(tsParticles); + // await window.tsParticles.load({ id: particleIdSelector, options }); + // })(); + // }; + } + const options = { + particles: { + number: { + value: 20, + }, + color: { + value: '#ffffff', + }, + links: { + enable: true, + distance: 200, + }, + shape: { + type: 'circle', + }, + opacity: { + value: 0.6, + }, + size: { + value: { + min: 2, + max: 4, + }, + }, + move: { + enable: true, + speed: 0.5, + }, + }, + background: { + color: '#016DFF', + }, + poisson: { + enable: true, + }, + fullScreen: { enable: false }, + }; + + await loadParticles(options); +} + +// eslint-disable-next-line no-unused-vars +async function checkForMobile() { + const isMobileView = isView('mobile'); + if (isMobileView && (!tsParticles && !loadAll)) { + return; + } + + if (isMobileView && tsParticles) { + const particles = tsParticles.domItem(0); + particles.pause(); + return; + } + + if (!isMobileView && (!tsParticles && !loadAll)) { + await init(); + return; + } + + const particles = tsParticles.domItem(0); + particles.play(); +} + +export default async function decorate(block, options) { + await init(block, options); + + // uncomment this line if you want the bubbles to stop moving on mobile + // window.addEventListener('resize', debounce(checkForMobile, 250)); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/percentage-vsb/percentage-vsb.css b/_src/blocks/percentage-vsb/percentage-vsb.css new file mode 100644 index 000000000..efabe30bc --- /dev/null +++ b/_src/blocks/percentage-vsb/percentage-vsb.css @@ -0,0 +1,109 @@ +/* stylelint-disable no-descending-specificity */ +.percentage-vsb-container { + display: flex; + justify-content: center; + font-family: 'IBM Plex Sans', sans-serif; +} + +.percentage-vsb-container.we-container{ + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.percentage-vsb-container a{ + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.percentage-vsb-container a:hover { + background-color: #d80000; + border: 2px solid #d80000; + cursor: pointer; +} + +.percentage-vsb-wrapper { + max-width: 630px; + display: flex; + flex-direction: column; + align-items: center; + +} + +.percentage-vsb-wrapper .columns-container{ + display:flex; + flex-direction: column; + gap:0; +} + +.percentage-vsb-wrapper .columns-container .col{ + width: 100%; + padding: 5px; +} + +.percentage-vsb-wrapper .title-class h2{ + font-size: 38px; + line-height: 40px; + margin-top: 1em; +} + +.percentage-vsb-wrapper .subtitle-class{ + font-size:18px; +} + +.percentage-vsb-wrapper .columns-container h4{ + font-size: 38px; + color: #F00F0F; + margin-top: 0; + margin-bottom: 9px; +} + +.percentage-vsb-wrapper .button-container{ + display: flex; + justify-content: center; + margin-top: 1em; +} + +@media (min-width: 768px) { + .percentage-vsb-wrapper .columns-container{ + display:flex; + flex-direction: row; + margin-top:35px; + margin-bottom: 42px; + gap:20px; + } + +.percentage-vsb-wrapper .columns-container .col{ + width: 33.33%; +} + +.percentage-vsb-wrapper .title-class h2{ + font-size:48px; + line-height: 55px; +} + +.percentage-vsb-wrapper .columns-container h4{ + font-size: 48px; + line-height: 55px; +} +} diff --git a/_src/blocks/percentage-vsb/percentage-vsb.js b/_src/blocks/percentage-vsb/percentage-vsb.js new file mode 100644 index 000000000..bb1fb553a --- /dev/null +++ b/_src/blocks/percentage-vsb/percentage-vsb.js @@ -0,0 +1,49 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + const [ + title, + subtitle, + button, + colTitle1, + colText1, + colTitle2, + colText2, + colTitle3, + colText3, + ] = block.children; + + title.classList.add('title-class'); + subtitle.classList.add('subtitle-class'); + const columnsContainer = document.createElement('div'); + columnsContainer.classList.add('columns-container'); + + const column1 = document.createElement('div'); + column1.appendChild(colTitle1); + column1.appendChild(colText1); + columnsContainer.appendChild(column1); + column1.classList.add('col'); + + const column2 = document.createElement('div'); + column2.appendChild(colTitle2); + column2.appendChild(colText2); + columnsContainer.appendChild(column2); + column2.classList.add('col'); + + const column3 = document.createElement('div'); + column3.appendChild(colTitle3); + column3.appendChild(colText3); + columnsContainer.appendChild(column3); + column3.classList.add('col'); + block.appendChild(columnsContainer); + button.classList.add('button-container'); + block.appendChild(button); + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/platform-link/platform-link.js b/_src/blocks/platform-link/platform-link.js new file mode 100644 index 000000000..5fb3c1a96 --- /dev/null +++ b/_src/blocks/platform-link/platform-link.js @@ -0,0 +1,15 @@ +import { getDatasetFromSection, openUrlForOs } from '../../scripts/utils/utils.js'; + +export default function decorate(block) { + block.classList.add('default-content-wrapper'); + const blockDataset = getDatasetFromSection(block); + + const { + linkandroid, linkios, linkmacos, linkwindows, + } = blockDataset; + + const freeDownloadButton = block.querySelector('a'); + if (freeDownloadButton) { + openUrlForOs(linkmacos, linkwindows, linkandroid, linkios, freeDownloadButton); + } +} diff --git a/solutions/blocks/product-comparison-table/product-comparison-table.css b/_src/blocks/product-comparison-table/product-comparison-table.css similarity index 65% rename from solutions/blocks/product-comparison-table/product-comparison-table.css rename to _src/blocks/product-comparison-table/product-comparison-table.css index 95caa7052..5ebc6ce2c 100644 --- a/solutions/blocks/product-comparison-table/product-comparison-table.css +++ b/_src/blocks/product-comparison-table/product-comparison-table.css @@ -17,6 +17,37 @@ padding-right: 0; } +.section.product-comparison-table-container .default-content-wrapper { + margin-bottom: 2em; +} + +.current-price-container p { + font-size: var(--body-font-size-m); + font-weight: var(--font-weight-boldest); +} + +div[role="cell"] p { + margin: 0; +} + +.product-comparison-price p:last-of-type { + color: #7e7e7e; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-regular); + line-height: var(--body-font-size-xs); + border-bottom: 1px dashed #dedede; + margin-bottom: 4px !important; + padding-bottom: 1.5em; +} + +.product-comparison-header div[role="columnheader"] p { + margin: 0; +} + +.section.product-comparison-table-container .default-content-wrapper p { + font-size: var(--body-font-size-m); +} + .column-fixed-width { width: 10.5rem; } @@ -54,6 +85,8 @@ .product-comparison-header div[role="columnheader"]:not(:first-child) { border: 1px solid var(--first-table-cell-color); flex: 1; + display: flex; + flex-direction: column; } .product-comparison-header div[role="columnheader"]:not(:first-child).active { @@ -83,36 +116,25 @@ .product-comparison-price { padding-top: 0.9375rem; margin: 0.9375rem 0.625rem 0; - border-top: 1px solid var(--horizontal-separator-color); -} - -.current-price-container p{ - font-size: var(--body-font-size-m); - font-weight: var(--font-weight-boldest); -} - -div[role="cell"] p { - margin: 0; -} - -.product-comparison-price p:last-of-type { - color: var(--product-comparison-text-color); -} - -.product-comparison-header div[role="columnheader"] p { - margin: 0; + border-top: 1px solid var(--horizontal-separator-color); } div[role="cell"] .button-container , .product-comparison-header div[role="columnheader"] .button-container{ margin-bottom: 0.3125rem; } +.section.product-comparison-table-container.migration p { + color: #7e7e7e; + font-size: 12px; +} + .product-comparison-header div[role="columnheader"] p:first-of-type { font-weight: var(--font-weight-bold); padding: 0; - color: var(--product-comparison-text-color); + color: #3c3c3c; text-align: center; - font-size: var(--body-font-size-xs); + font-size: var(--body-font-size-s); + flex-grow: 1; } .product-comparison-header div[role="cell"] p:first-of-type { @@ -139,6 +161,15 @@ div[role="cell"] p.button-container a, .product-comparison-header div[role="colu background-color: unset; } +.product-comparison-header div[role="columnheader"] p.button-container a:hover { + background-color: var(--button-primary-background-color); + color: white; +} + +.product-comparison-header div[role="columnheader"] p.button-container a:hover::after { + background-color: white!important; +} + .product-comparison-header div[role="columnheader"].active p.button-container a, .product-comparison-header div[role="columnheader"] p.button-container.red a { background-color: var(--button-background-color); @@ -165,12 +196,12 @@ div[role="cell"] p:last-of-type.product-comparison-header-subtitle, } .product-comparison-header div[role="columnheader"] h3 { - margin: 3rem 0.625rem 0.25rem; + margin: 2em 1em 5px; font-size: var(--heading-font-size-s); - min-height: 4rem; + font-weight: var(--font-weight-regular); } -.product-comparison-header div[role="columnheader"] .old-price-container p{ +.product-comparison-header div[role="columnheader"] .old-price-container p { font-size: var(--body-font-size-xxs); line-height: 1.2; color: var(--product-comparison-text-color); @@ -240,15 +271,16 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { background-color: var(--table-cell-color); border-right: 1px solid var(--white-color); border-bottom: 1px solid var(--white-color); - text-transform: capitalize; } .product-comparison-table div[role='cell']:first-child { background-color: var(--first-table-cell-color); padding: 0.875rem 1.75rem 1.0625rem 2.125rem; width: 100%; - font-weight: var(--font-weight-bold); text-align: center; + font-size: var(--body-font-size-s); + font-weight: var(--font-weight-regular); + letter-spacing: .006em; } .product-comparison-table div[role='cell']:not(:first-child) { @@ -277,6 +309,35 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { border-right: 1px solid var(--background-color-light-sky-blue); } +.product-comparison-table .old-price-box, .product-comparison-table .new-price-box{ + font-family: Arial, sans-serif; +} + +@media (max-width: 580px) { + .product-comparison-table.with-fixed-width { + width: 100%; + } + + .product-comparison-price .current-price-container, .product-comparison-header div[role="columnheader"] h3 { + font-size: var(--body-font-size-xs); + } + + .product-comparison-header div[role="columnheader"] h3 { + margin: 10px 0 0; + } + + .product-comparison-header div[role="columnheader"] p { + min-height: 3rem; + } + + .product-comparison-header div[role="columnheader"] p.button-container.red a { + font-size: var(--body-font-size-xxs); + padding: 5px 0; + text-align: center; + width: 100%; + } +} + @media (min-width: 580px) { .product-comparison-table-wrapper { margin: 0 auto; @@ -329,12 +390,13 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { .product-comparison-header div[role="columnheader"] h3 { font-size: var(--heading-font-size-m); + min-height: unset !important; } .product-comparison-header-subtitle { - padding: 0 4rem; + padding: 0 1em; } - + .product-comparison-table div[role='cell'] { display: table-cell; @@ -343,6 +405,7 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { .product-comparison-table div[role='cell']:first-child { width: 25%; text-align: left; + border-top-left-radius: 8px; } div[role="row"].expandable-row div[role="cell"] p:first-of-type { @@ -353,14 +416,14 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { .product-comparison-table div[role='cell'] > div { display: flex; justify-content: center; - + } .collapsed.hidden-rows-wrapper { max-height: 0; transition: max-height .5s ease-in-out; overflow: hidden; - + } .expanded.hidden-rows-wrapper { @@ -467,4 +530,169 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { .display-price-below .product-comparison-price { border: none; +} + +.product-comparison-table.two-products { + width: 100%; +} + +.section.product-comparison-table-container .old-price-box span { + color: #7e7e7e; + font-size: var(--body-font-size-m); + font-weight: var(--font-weight-regular); + line-height: 1.2; +} + +.section.product-comparison-table-container .new-price-box { + font-size: var(--heading-font-size-l); + font-weight: var(--font-weight-boldest); +} + +@media (width <= 1202px) { + .product-comparison-table div[role='columnheader']:nth-child(1) > h2 { + font-size: var(--heading-font-size-l); + } + + .section.product-comparison-table-container.migration .old-price-box span { + font-size: 13px; + flex-direction: column; + display: flex !important; + } + + .section.product-comparison-table-container.migration .old-price-box span:first-of-type { + text-align: left; + } + + .section.product-comparison-table-container.migration h3 { + font-size: 21px !important; + margin-top: 1em !important; + } + + .section.product-comparison-table-container.migration .new-price-box .total-text { + font-size: 16px; + } + } + + .section.product-comparison-table-container.migration .product-comparison-price { + border: 0 none!important; +} + +.section.product-comparison-table-container.migration h3 { + font-family: roboto, sans-serif; + font-size: 24px !important; + color: black !important; + font-weight: 500; + line-height: 1.25; +} + +.section.product-comparison-table-container.migration .old-price-box { + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px dashed #dedede; + padding-bottom: 10px; +} + +.section.product-comparison-table-container.migration .old-price-box .savings { + display: block; + background: rgb(44 180 61 / 20%); + border-radius: 8px; + padding: 1px 9px 5px; + text-align: right; + color: #2cb43d; + font-size: 14px; + font-weight: 500; + line-height: 1.5; +} + +.section.product-comparison-table-container.migration .new-price-box { + display: flex; + justify-content: space-between; + align-items: center; + margin: 10px auto 0; + font-size: 24px; + font-weight: 700; + line-height: .9; + color: black; +} + +.section.product-comparison-table-container.migration .new-price-box .total-text { + color: #3c3c3c; + display: inline-block; + font-size: 18px; + line-height: 1.25; + margin-right: auto; + padding: 0; + font-weight: normal; +} + +.section.product-comparison-table-container.migration p.button-container { + margin-bottom: 2em; +} + +.section.product-comparison-table-container.migration .product-comparison-price > p:last-of-type{ + text-align: right; + color: #3c3c3c; + display: block; + font-size: 10px; + font-weight: 400; + line-height: 2; + margin-bottom: 0; +} + +@media (max-width: 992px) { + .section.product-comparison-table-container .old-price-box span { + font-size: var(--body-font-size-xxs); + } +} + +@media (max-width: 768px) { + .product-comparison-header div[role="columnheader"] h3 { + font-size: var(--heading-font-size-xs); + margin: 1em 1em 5px; + } + + .product-comparison-header div[role="columnheader"] p:first-of-type { + font-size: var(--body-font-size-xs); + } + + .section.product-comparison-table-container .new-price-box { + font-size: var(--heading-font-size-s); + } + + .product-comparison-table div[role='cell']:first-child { + font-size: var(--body-font-size-xs); + } +} + +@media (max-width: 500px) { + .product-comparison-header div[role="columnheader"]:not(:first-child) { + width: 33%; + } + + .product-comparison-header div[role="columnheader"] h3 { + font-size: var(--heading-font-size-xxs); + margin: 1em 0 5px; + } + + .product-comparison-price p:last-of-type { + font-size: var(--body-font-size-xxs); + } + + .product-comparison-header div[role="columnheader"] p { + min-height: unset; + } + + div[role="cell"] p.button-container a, .product-comparison-header div[role="columnheader"] p.button-container a { + padding: 4px 26px 6px 18px; + font-size: var(--body-font-size-xs); + } + + .product-comparison-table div[role='cell']:not(:first-child) { + padding: 1em; + } + + .section.product-comparison-table-container .default-content-wrapper p { + font-size: var(--body-font-size-s); + } } \ No newline at end of file diff --git a/solutions/blocks/product-comparison-table/product-comparison-table.js b/_src/blocks/product-comparison-table/product-comparison-table.js similarity index 76% rename from solutions/blocks/product-comparison-table/product-comparison-table.js rename to _src/blocks/product-comparison-table/product-comparison-table.js index 42c9e0a23..eef6343d6 100644 --- a/solutions/blocks/product-comparison-table/product-comparison-table.js +++ b/_src/blocks/product-comparison-table/product-comparison-table.js @@ -1,10 +1,16 @@ -import { createNanoBlock, renderNanoBlocks, fetchProduct } from '../../scripts/utils.js'; +import { createNanoBlock, renderNanoBlocks, matchHeights } from '../../scripts/utils/utils.js'; -const fetchedProducts = []; +createNanoBlock('priceComparison', (code, variant, label, block, productIndex, columnEl) => { + columnEl.setAttribute('data-store-id', code); + columnEl.setAttribute('data-store-option', variant); + columnEl.setAttribute('data-store-department', 'consumer'); + columnEl.setAttribute('data-store-event', 'product-comparison'); + columnEl.setAttribute('data-store-context', ''); -createNanoBlock('price-comparison', (code, variant, label) => { const priceRoot = document.createElement('div'); priceRoot.classList.add('product-comparison-price'); + const oldPriceText = block.closest('.section').dataset.old_price_text ?? ''; + const newPriceLabel = block.closest('.section').dataset.new_price_label ?? ''; const oldPriceElement = document.createElement('p'); priceRoot.appendChild(oldPriceElement); oldPriceElement.innerText = '-'; @@ -15,20 +21,38 @@ createNanoBlock('price-comparison', (code, variant, label) => { priceElement.classList.add('current-price-container'); const priceAppliedOnTime = document.createElement('p'); priceRoot.appendChild(priceAppliedOnTime); + // create a mock buyzone for free products + if (code.includes('free')) { + oldPriceElement.innerHTML = ` +
      +
      + `; + priceElement.innerHTML = `
      + ${label} + +
      `; + priceAppliedOnTime.innerHTML = '

      '; + return priceRoot; + } - fetchProduct(code, variant) - .then((product) => { - fetchedProducts.push({ code, variant, product }); - // eslint-disable-next-line camelcase - const { price, discount: { discounted_price: discounted }, currency_iso: currency } = product; - oldPriceElement.innerHTML = `Old Price ${price} ${currency}`; - priceElement.innerHTML = `${discounted} ${currency}`; - priceAppliedOnTime.innerHTML = label; - }) - .catch((err) => { - // eslint-disable-next-line no-console - console.error(err); - }); + oldPriceElement.innerHTML = ` +

      + ${oldPriceText} + Savings +
      `; + priceElement.innerHTML = ` +
      + + ${newPriceLabel} +
      `; + priceAppliedOnTime.innerHTML = label; + + // update buy link + const buyLink = columnEl.querySelector('.button-container a'); + if (buyLink.href.includes('/buy/') || buyLink.href.includes('#buylink')) { + buyLink.href = '#'; + buyLink.setAttribute('data-store-buy-link', ''); + } return priceRoot; }); @@ -151,7 +175,7 @@ function extractTextFromStrongTagToParent(element) { }); } - if (element.tagName === 'STRONG') { + if (element.tagName === 'STRONG' && element.parentElement) { element.parentElement.innerHTML = element.textContent; } } @@ -159,16 +183,14 @@ function extractTextFromStrongTagToParent(element) { function buildTableHeader(block) { const header = block.querySelector('div > div'); header.classList.add('product-comparison-header'); - [...header.children].forEach((headerColumn) => { const buttonSection = headerColumn.querySelector('p.button-container'); - if (buttonSection) { const paragraphBefore = buttonSection.previousElementSibling; paragraphBefore?.classList.add('per-year-statement'); const paragraphAfter = buttonSection.nextElementSibling; paragraphAfter?.classList.add('product-comparison-header-subtitle'); - paragraphAfter?.nextElementSibling.classList.add('product-comparison-header-subtitle'); + paragraphAfter?.nextElementSibling?.classList.add('product-comparison-header-subtitle'); } }); } @@ -266,5 +288,15 @@ export default function decorate(block) { } extractTextFromStrongTagToParent(block); - renderNanoBlocks(block); + const headerList = [...block.children[0].children].slice(1); + const lastRowWithPrice = block.querySelector('.product-comparison-last-row-with-prices'); + [...headerList, lastRowWithPrice].forEach((item, idx) => { + if (item) { + renderNanoBlocks(item, undefined, idx, block); + } + }); + + matchHeights(block, 'h3'); + matchHeights(block, '.old-price-container'); + matchHeights(block, '.product-comparison-price'); } diff --git a/_src/blocks/products-sideview/products-sideview.css b/_src/blocks/products-sideview/products-sideview.css new file mode 100644 index 000000000..5e3a201bf --- /dev/null +++ b/_src/blocks/products-sideview/products-sideview.css @@ -0,0 +1,329 @@ +:root { + --tab-header-color-blue: #005ed9; + --tab-description-color-light-grey: #3c3c3c; + --tab-emphasis-color: #2cb43d; +} + +.products-sideview .features-wrapper { + background: #eff6ff; + padding: 30px; + border-radius: 0 0 20px 20px; +} + +.products-sideview .features-wrapper > p, +.products-sideview .pricing-wrapper > p { + font-size: 18px; + line-height: 1.5; + letter-spacing: .006em; + font-weight: var(--font-weight-regular); +} + +.products-sideview .pricing-wrapper { + background: #f6f6f6; + border-radius: 20px 20px 0 0; + padding: 30px; +} + +.products-sideview .prod-oldprice { + text-decoration: line-through; +} + +.products-sideview .price-element-wrapper { + margin: 20px 0; + font-family: Arial, sans-serif;; +} + +.products-sideview .pricing-wrapper > p:last-child { + text-align: center; +} + +.products-sideview p.button-container > a { + width: 100%; + justify-content: center; +} + +.products-sideview .price { + font-size: 32px; + font-weight: bold; +} + +.products-sideview .tag-blue { + background: var(--tab-header-color-blue); + color: white; + padding: 0 10px; + border-radius: 10px; + margin-left: 5px; + font-size: 14px; + line-height: 1; + font-weight: bolder; +} + +.products-sideview-radio { + display: flex; + align-items: center; + margin-left: -2px; + margin-top: 20px; + margin-bottom: 20px; +} + +.products-sideview-radio input { + width: 25px; + height: 25px; + margin: 0; +} + +.products-sideview-radio label { + margin-left: 5px; +} + +.products-sideview-radio input:nth-last-child(2) { + margin-left: 20px; +} + +.products-sideview-selector { + position: relative; +} + +.products-sideview-selector select { /* Remove default styling */ + appearance: none; + width: 100%; + border: 1px solid #ccc; + background-color: white; + padding: 10px; + font-size: 18px; + font-weight: bold; + border-radius: 5px; +} + +.products-sideview-selector::after { + content: ''; + background: url("/_src/icons/tabs_arrow.svg") no-repeat; + position: absolute; + top: 50%; + right: 10px; + transform: rotate(180deg) translateY(50%); + pointer-events: none; /* Prevent the arrow from blocking clicks */ + width: 15px; + height: 15px; +} + +.products-sideview li { + padding: 0; + margin: 0 0 10px; +} + + +.products-sideview .benefits-list > li { + position: relative; + padding-left: 25px; + margin: 0 0 5px; +} + +.products-sideview .benefits-list > li::before { + content: url("/_src/icons/checkmark-green-circle.svg"); + position: absolute; + left: 0; + top: 4px; + width: 18px; + height: 18px; +} + +.products-sideview-wrapper { + padding: 0 var(--body-padding); +} + +.products-sideview { + /* box-shadow: 0 3px 8px 0 var(--dark-shadow); */ + + /* border-radius: 8px; */ + + /* padding: 40px 15px 20px; */ +} + +.products-sideview > div { + display: flex; + flex-direction: column; + align-items: stretch; +} + +.products-sideview img { + width: 100%; +} + +.products-sideview > div > div { + position: relative; + order: 1; +} + +.products-sideview > div > div:last-child::after { + display: none; +} + +.products-sideview > div > .features-img-col { + order: 0; +} + +.products-sideview > div > .features-img-col img { + display: block; +} + +.products-sideview p.features-tabs-hidden { + display: none; +} + +.products-sideview ul { + padding: 0; +} + +.products-sideview .features-tabs li > a { + color: var(--tab-header-color-blue); + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + position: relative; + display: inline-block; + letter-spacing: .004em; + cursor: pointer; + text-decoration: none; + padding-left: 25px; +} + +.products-sideview .features-tabs li > a::after { + content: ""; + position: absolute; + left: 0; + top: 0; + display: inline-block; + width: 14px; + height: 8px; + margin: 9px 3px; + background: url("/_src/icons/tabs_arrow.svg") no-repeat; + background-size: 100%; + transform: rotate(180deg); + transition: all .3s linear; +} + +.products-sideview .features-tabs li > a.is-open::after { + transform: rotate(0) +} + +.products-sideview .features-tabs .features-tabs-content { + opacity: 0; + height: 0; + overflow: hidden; + margin-left: 25px; + transition: all 0.3s ease-in-out; +} + +.products-sideview .features-tabs .features-tabs-content.expanded { + opacity: 1; + height: auto; + transition: all 0.3s ease-in-out; + display: block; +} + +.products-sideview .features-tabs .features-tabs-content > p { + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-regular); + line-height: 1.6; +} + +@media (min-width: 480px) { + .products-sideview .features-tabs li > a { + font-size: 15px; + } +} + +@media (min-width: 768px) { + .products-sideview .features-wrapper { + border-radius: 0 20px 20px 0; + width: 50%; + } + + .products-sideview .pricing-wrapper { + border-radius: 20px 0 0 20px; /* desktop */ + width: 50% + } + + .products-sideview .pricing-wrapper h4 { + font-size: 26px; + line-height: 32.5px; + font-weight: 700; + } + + .products-sideview .features-wrapper h2 { + font-size: 38px; + line-height: 45.6px; + font-weight: 700; + } + + .features-tabs { + display: flex; + flex-wrap: wrap; + column-gap: 30px; + } + + .features-tabs > li { + position: relative; + } + + .products-sideview > div { + flex-flow: wrap; + } + + .products-sideview > div > div { + padding: 0 20px 20px; + } + + .products-sideview-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + .products-sideview > div > div:nth-child(2)::after { + display:none; + } +} + +@media (min-width: 993px) { + .products-sideview.features-3-cols > div > div { + width: calc(33.33% - 30px); + margin: 0 15px; + } + + .products-sideview.features-3-cols > div > div:nth-child(2)::after { + display:block; + } + + .products-sideview.features-2-cols > div > div:nth-child(2)::after { + display:none; + } +} + +@media (min-width: 1200px) { + .products-sideview .pricing-wrapper { + width: 33.33%; + } + + .products-sideview .features-wrapper { + width: 66.66%; + min-height: fit-content; + } + + .products-sideview .features-tabs > li { + width: calc(50% - 30px); + flex-shrink: 0; + margin-bottom: 25px; + } + + .products-sideview .features-tabs .features-tabs-content > p { + font-size: var(--body-font-size-xs); + } +} + +@media (min-width: 1600px) { /* large desktop */ + .products-sideview-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} diff --git a/_src/blocks/products-sideview/products-sideview.js b/_src/blocks/products-sideview/products-sideview.js new file mode 100644 index 000000000..c183dec24 --- /dev/null +++ b/_src/blocks/products-sideview/products-sideview.js @@ -0,0 +1,278 @@ +import { + createNanoBlock, + getDatasetFromSection, + renderNanoBlocks, +} from '../../scripts/utils/utils.js'; + +const state = { + firstProduct: null, + secondProduct: null, + currentProduct: null, + mode: 'm', // "m" or "y", + membersIndex: 0, + blockDataset: null, +}; + +const MEMBERS_MAP = new Map(); + +function expandItem(content) { + content.style.height = `${content.scrollHeight}px`; + const transitionEndCallback = () => { + content.removeEventListener('transitionend', transitionEndCallback); + content.style.height = 'auto'; + }; + content.addEventListener('transitionend', transitionEndCallback); + content.classList.add('expanded'); +} + +function collapseItem(content) { + content.style.height = `${content.scrollHeight}px`; + requestAnimationFrame(() => { + content.classList.remove('expanded'); + content.style.height = 0; + }); +} + +function eventListener(ul) { + return (event) => { + let target = null; + + // find ancestor a tag + if (event.target.tagName !== 'A') { + target = event.target.closest('a'); + } else { + target = event.target; + } + + // if the clicked node is not open then open it + if (!target.classList.contains('is-open')) { + target.classList.add('is-open'); + + // if the clicked node has children then toggle the expanded class + if (target.parentNode.children.length > 1) { + target.parentNode.querySelectorAll('.features-tabs-content').forEach((content) => { + expandItem(content); + }); + } + + // hid the other tabs + ul.querySelectorAll('li').forEach((collapsedLi) => { + if (collapsedLi !== target.parentNode) { + collapsedLi.children[0].classList.remove('is-open'); + collapsedLi.querySelectorAll('.features-tabs-content').forEach((content) => { + collapseItem(content); + }); + } + }); + } else { + target.classList.remove('is-open'); + // if the clicked node has children then toggle the expanded class + if (target.parentNode.children.length > 1) { + target.parentNode.querySelectorAll('.features-tabs-content').forEach((content) => { + collapseItem(content); + }); + } + } + }; +} + +function extractFeatures(col) { + const ul = document.createElement('ul'); + ul.classList.add('features-tabs'); + + // select all h4 tags as feature titles + col.querySelectorAll('h4').forEach((h4) => { + const li = document.createElement('li'); + ul.appendChild(li); + + const a = document.createElement('a'); + a.setAttribute('href', '#'); + + // register click event on a tag + + a.addEventListener('click', (event) => { + event.preventDefault(); + eventListener(ul)(event); + }); + + h4.childNodes.forEach((node) => { + if (node.nodeType === Node.TEXT_NODE) { + a.appendChild(document.createTextNode(node.textContent)); + } else { + a.appendChild(node); + } + }); + + a.classList.add('features-tabs-title'); + + li.appendChild(a); + + // all descendants of a that have class tag + a.querySelectorAll('.tag').forEach((tag) => { + li.appendChild(tag); + }); + + const content = document.createElement('div'); + content.classList.add('features-tabs-content'); + li.appendChild(content); + + // every oaragraph until next h4 + let nextElement = h4.nextElementSibling; + while (nextElement && nextElement.tagName !== 'H4') { + content.appendChild(nextElement); + nextElement = h4.nextElementSibling; + } + + ul.appendChild(li); + + h4.remove(); + }); + + return ul; +} + +function updateBuyLink(block) { + const buyLink = block.querySelector('.button-container > .button'); + if (buyLink) { + buyLink.href = '#'; + buyLink.setAttribute('data-store-buy-link', ''); + } +} + +function renderPrice(block, _firstProduct, secondProduct) { + const variant = '5-1'; + const priceElement = document.createElement('div'); + priceElement.classList.add('price-element-wrapper'); + + const oldPrice = document.createElement('div'); + oldPrice.classList.add('prod-oldprice', 'await-loader'); + oldPrice.setAttribute('data-store-price', 'full'); + oldPrice.setAttribute('data-store-hide', 'no-price=discounted'); + + const el = document.createElement('DIV'); + el.classList.add('price'); + el.classList.add('await-loader'); + block.setAttribute('data-store-context', ''); + block.setAttribute('data-store-id', secondProduct); + block.setAttribute('data-store-option', variant); + block.setAttribute('data-store-department', 'consumer'); + block.setAttribute('data-store-event', 'main-product-loaded'); + el.setAttribute('data-store-price', 'discounted||full'); + + priceElement.appendChild(oldPrice); + priceElement.appendChild(el); + updateBuyLink(block); + return priceElement; +} + +function renderRadioGroup(block) { + const metadata = block.parentElement.parentElement.dataset; + const [firstProduct, secondProduct] = metadata.price.split(','); + const el = document.createElement('DIV'); + el.classList.add('products-sideview-radio'); + el.innerHTML = ` + + + + + + `; + return el; +} + +function getBlueTags(block) { + let blueTags = block.querySelectorAll('.tag-blue'); + if (!blueTags.length) { + const benefitsList = block.querySelector('ul'); + benefitsList?.classList.add('benefits-list'); + const benefitsListElements = benefitsList?.querySelectorAll('li'); + benefitsListElements?.forEach((element) => { + const blueTag = document.createElement('span'); + blueTag.classList.add('tag-blue'); + element.insertAdjacentElement('beforeend', blueTag); + }); + blueTags = block.querySelectorAll('.tag-blue'); + } + return blueTags; +} + +function updateBenefits(block, selectEl, metadata) { + const blueTags = getBlueTags(block); + const selectedOption = [...selectEl.options].find((option) => option.hasAttribute('selected')); + const neededIndex = [...selectEl.options].indexOf(selectedOption); + const updatedBenefits = JSON.parse(metadata[neededIndex]); + let counter = 0; + blueTags.forEach((tag) => { + // eslint-disable-next-line no-plusplus + tag.textContent = `x${updatedBenefits[counter++]}`; + }); +} + +function renderSelector(block, ...options) { + const selectorOptions = options + .filter((option) => option && !Number.isNaN(Number(option))) + .map((opt) => Number(opt)); + const defaultSelection = Number(state.blockDataset.defaultselection) || selectorOptions[1]; + const el = document.createElement('div'); + el.classList.add('products-sideview-selector'); + + el.innerHTML = ` + + `; + + const selectEl = el.querySelector('select'); + const metadata = block.parentElement.parentElement.dataset; + selectEl.value = defaultSelection; + + selectEl.addEventListener('change', (e) => { + [...selectEl.options].forEach((option) => option.removeAttribute('selected')); + [...selectEl.options].find((option) => option.value === e.target.value)?.setAttribute('selected', ''); + updateBenefits(block, selectEl, metadata.benefits.split(',,')); + }); + + updateBenefits(block, selectEl, metadata.benefits.split(',,')); + + return el; +} + +createNanoBlock('price', renderPrice); +createNanoBlock('monthlyYearly', renderRadioGroup); +createNanoBlock('selectMembers', renderSelector); + +function initMembersMap() { + const selectMembers = state.blockDataset.selectmembers.trim().split(','); + selectMembers.forEach((member, index) => MEMBERS_MAP.set(index, Number(member))); +} + +export default function decorate(block) { + const blockDataset = getDatasetFromSection(block); + state.blockDataset = blockDataset; + + initMembersMap(); + + block.firstElementChild.classList.add('d-flex'); + block.firstElementChild.firstElementChild.classList.add('pricing-wrapper'); + block.firstElementChild.lastElementChild.classList.add('features-wrapper'); + + renderNanoBlocks(block.firstElementChild, block); + + const cols = [...block.firstElementChild.children]; + block.classList.add(`features-${cols.length}-cols`); + + const col = block.children[0].children[1]; + col.appendChild(extractFeatures(col)); +} diff --git a/solutions/blocks/products/products.css b/_src/blocks/products/products.css similarity index 83% rename from solutions/blocks/products/products.css rename to _src/blocks/products/products.css index edb933227..b77763dea 100644 --- a/solutions/blocks/products/products.css +++ b/_src/blocks/products/products.css @@ -37,6 +37,67 @@ flex-grow: 0; } +.v2 .product-card .price { + flex: 1; + justify-content: center; + align-items: flex-end; + display: flex; +} + +.product-card .price:last-of-type { + font-weight: var(--font-weight-bold); + margin-bottom: 0; +} + +.v2 .product-card .price:last-of-type { + flex: 0; +} + +.product-card .price em { + color: black; + font-size: var(--body-font-size-xxs); + display: inline-block; + font-style: normal; + line-height: 1.4em; + font-weight: bold; +} + +.v2 .product-card .price:last-of-type em { + color: #7e7e7e; + font-size: var(--body-font-size-xxxs); + font-weight: var(--font-weight-bold); + line-height: 2.4; +} + +.product-card p { + font-size: var(--body-font-size-s); + color: #3c3c3c; + margin: 0; +} + +.product-card p:nth-of-type(2) { + font-size: var(--body-font-size-xs); +} + +.product-card .price ~ p { + font-size:var(--body-font-size-xxs); + color: #7e7e7e; +} + +.v2 .product-card p:last-of-type { + line-height: 16px; +} + +.product-card hr { + margin: 17px 0; + border-bottom: 1px solid #e5e7eb; + width: 100%; +} + +.v2 .product-card hr { + margin: 12px 0; +} + .product-card .button-container { flex-grow: 0; display: flex; @@ -45,6 +106,10 @@ margin: 25px 0 5px; } +.v2 .product-card .button-container { + margin: 15px 0; +} + .products.compact .product-card, .products.plans .product-card { text-align: center; } @@ -57,27 +122,12 @@ padding-top: var(--highlight-spacing); } -.product-card p { - font-size: var(--body-font-size-s); - color: #3c3c3c; - margin: 0; -} - -.product-card p:nth-of-type(2) { - font-size: var(--body-font-size-xs); -} - .product-card p a { - text-decoration: underline; + text-decoration: none; color: inherit; color: var(--link-color); } -.product-card .price ~ p { - font-size:var(--body-font-size-xxs); - color: #666; -} - .products.plans .product-card p { font-size: var(--body-font-size-xxs); } @@ -121,7 +171,7 @@ } .products.compact .product-card h3, .products.plans .product-card h3 { - font-size: var(--body-font-size-s); + font-size: var(--body-font-size-m); margin: 0; flex: 0; } @@ -166,12 +216,12 @@ } .product-card .featured { - color: white; - background-color: #218728; - border-radius: 15px; - font-size: var(--body-font-size-xxs); - padding: 5px 15px; - font-weight: bold; + color: #2cb43d; + background-color: rgb(44 180 61 / 20%); + border-radius: 8px; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + padding: 2px 8px; display: inline-block; align-self: self-start; margin-bottom: 10px; @@ -179,7 +229,7 @@ :is(.products.compact, .products.plans) .product-card .featured { align-self: center; - margin: 10px 0 15px; + margin: 7px 0; } .products:not(.compact) .product-card img { @@ -195,6 +245,7 @@ margin: 60px 0 25px; top: auto; right: auto; + display: none; } .products.compact .product-card .featured ~ p img { @@ -221,7 +272,7 @@ } .product-card .ul-header-text { - margin: 1.5rem 0; + margin: 1.5rem 0; text-align: left; } @@ -282,14 +333,9 @@ text-decoration: underline; } -.product-card .price:last-of-type { - font-weight: 700; - margin-bottom: 15px; -} - .products.plans .product-card .price .old-price { font-weight: normal; - font-size: var(--body-font-size-l); + font-size: var(--body-font-size-xl); color: #666; } @@ -299,19 +345,9 @@ .products.compact .product-card .price strong, .products.plans .product-card .price strong { font-size: var(--heading-font-size-l); -} - -.product-card .price em { - font-size: var(--body-font-size-xxs); - display: block; - font-style: normal; - line-height: 1.4em; -} - -.product-card hr { - margin: 10px; - border-bottom: 1px solid #e5e7eb; - width: 100%; + font-weight: var(--font-weight-bolder); + display: flex; + justify-content: center; } .two-columns .columns .product-card hr { @@ -348,11 +384,15 @@ right: 17px; } +.product-card .price.nanoblock, .product-card .featured.nanoblock{ + font-family: Arial, sans-serif; +} + @media (max-width: 480px) { .product-card a.button::after { top: calc(50% - 10px); } - + } .product-card .button-text { @@ -363,7 +403,7 @@ .product-card ul.variant-selector { list-style: none; padding: 0; - margin: 4px 0 10px; + margin: 15px 0; } .product-card ul.variant-selector > li { @@ -455,20 +495,23 @@ } @media (min-width: 1200px) { /* desktop variation */ - .products:not(.compact) .product-card img { + .products:not(.compact, .plans) .product-card img { display: inline; position: absolute; - object-position: -60px 22px; - object-fit: cover; + object-position: -10px center; + object-fit:fill; border-radius: 50%; width: 250px; height: 250px; top: -42px; right: -60px; - border: 20px white solid; + border: 20px white solid; } -} + .product-card .img-adjacent-text{ + width: 74%; + } +} @media (min-width: 1600px) { /* large desktop */ .products-wrapper { @@ -478,17 +521,20 @@ .product-card .highlight { width: 100%; + height: 40px; position: absolute; top: 0; left: 0; - background-color: #218728; + background: #2cb43d; border-top-left-radius: 8px; border-top-right-radius: 8px; - padding: 4px 0 8px; - font-size: 18px; - font-weight: 700; + font-weight: var(--font-weight-bolder); color: #fff; letter-spacing: .96px; + display: flex; + justify-content: center; + align-items: center; + font-size: 12px; } .product-card .discount { @@ -537,7 +583,7 @@ } .products.compare .product-card .featured { - font-size: var(--body-font-size-s); + font-size: var(--body-font-size-s); margin: 0 auto 32px; } @@ -684,4 +730,54 @@ font-size: 20px; } +} + +@media (min-width: 310px) and (max-width: 768px) { + .product-card { + width: 310px; + margin: 1em auto; + } +} + +@media (max-width: 500px) { + .products.compact .product-card, .products.plans .product-card { + width: 100%!important; + max-width: unset!important; + } +} + +@media (max-width: 768px) { + .products.plans { + flex-direction: column; + } + + .products.plans .product-card .price .old-price.no-old-price { + display: none; + } + + .product-card .featured.no-save-price { + display: none; + } + + .products.plans .product-card { + margin: 0 auto; + max-width: unset; + width: 310px; + } +} + +@media (max-width: 992px) { + .products.compact, .products.plans { + --max-columns: 2; + + display: flex; + flex-wrap: wrap; + text-align: center; + justify-content: center; + } + + .products.compact .product-card, .products.plans .product-card { + max-width: unset; + width: 310px; + } } \ No newline at end of file diff --git a/_src/blocks/products/products.js b/_src/blocks/products/products.js new file mode 100644 index 000000000..e4dff1cea --- /dev/null +++ b/_src/blocks/products/products.js @@ -0,0 +1,459 @@ +import { Constants } from '../../scripts/libs/constants.js'; +import { + createNanoBlock, + renderNanoBlocks, + createTag, + matchHeights, + checkIfConsumerPage, +} from '../../scripts/utils/utils.js'; + +// all avaiable text variables +const TEXT_VARIABLES_MAPPING = [ + { + variable: 'percent', + storeVariable: '{DISCOUNT_PERCENTAGE}', + }, +]; + +/** + * Nanoblock representing the plan selectors. + * If only one plan is declared, the plan selector will not be visible. + * @param plans The list of plans to display [ labelToDisplay, productCode, variantId, ... ] + * @param defaultSelection The default selection. + * @returns Root node of the nanoblock + */ +function renderPlanSelector(plans, defaultSelection) { + // TODO: Remove unecessary div + const root = document.createElement('div'); + const ul = document.createElement('ul'); + ul.classList.add('variant-selector'); + root.appendChild(ul); + + if (plans.length === 3) { + ul.style.display = 'none'; + } + + for (let idx = 0; idx < plans.length - 2; idx += 3) { + const label = plans[idx]; + const liStoreParameters = {}; + + if (Number(defaultSelection)) { + liStoreParameters['data-store-click-set-devices'] = label; + } else { + const productCode = plans[idx + 1]; + const variation = plans[idx + 2]; + liStoreParameters['data-store-click-set-product'] = ''; + liStoreParameters['data-store-product-id'] = productCode; + liStoreParameters['data-store-department'] = 'consumer'; + liStoreParameters['data-product-type'] = Constants.PRODUCT_ID_MAPPINGS[productCode].isMonthlyProduct ? 'monthly' : 'yearly'; + liStoreParameters['data-store-product-option'] = variation; + } + + const li = createTag( + 'li', + liStoreParameters, + `${label}`, + ); + + // set the default selection + if (defaultSelection === label) { + li.classList.add('active'); + li.checked = true; + } + + li.addEventListener('click', () => { + const previousButtonActive = root.querySelector('.active'); + if (previousButtonActive) { + previousButtonActive.classList.remove('active'); + previousButtonActive.checked = false; + } + li.classList.add('active'); + li.checked = true; + }); + + ul.appendChild(li); + } + + return root; +} + +/** + * Nanoblock representing the old product price + * @param text The text located before the price + * @param monthly Show the monthly price if equal to 'monthly' + * @returns Root node of the nanoblock + */ +function renderOldPrice(text = '', monthly = '') { + // TODO: simplify CSS + const oldPrice = document.createElement('del'); + if (monthly.toLowerCase() === 'monthly') { + oldPrice.setAttribute('data-store-price', 'full-monthly'); + } else { + oldPrice.setAttribute('data-store-price', 'full'); + } + + const root = createTag( + 'div', + { + 'data-store-hide': 'no-price=discounted;type=visibility', + class: 'price await-loader', + }, + `${text} ${oldPrice.outerHTML}`, + ); + + // insert text to mark monthly price + if (monthly.toLowerCase() === 'monthly') { + root.querySelector('.old-price').insertAdjacentHTML('beforeend', '/mo'); + } + + return root; +} + +/** + * Nanoblock representing the new product price + * @param text The text located before the price + * @param monthly Show the monthly price if equal to 'monthly' + * @returns Root node of the nanoblock + */ +function renderPrice(text = '', monthly = '', monthTranslation = 'mo') { + // TODO simplify CSS + const newPrice = document.createElement('strong'); + if (monthly.toLowerCase() === 'monthly') { + newPrice.setAttribute('data-store-price', 'discounted-monthly||full-monthly'); + } else { + newPrice.setAttribute('data-store-price', 'discounted||full'); + } + + const root = createTag( + 'div', + { + class: 'price await-loader', + }, + `${text} ${newPrice.outerHTML}`, + ); + + // insert text to mark monthly price + if (monthly.toLowerCase() === 'monthly') { + root.querySelector('.new-price').insertAdjacentHTML('beforeend', `/${monthTranslation}`); + } + + return root; +} + +/** + * Renders the green section on top of the product card highlighting the potential savings + * @param text Text to display + * @param percent Show the saving in percentage if equals to `percent` + * @returns Root node of the nanoblock + */ +function renderHighlightSavings(text = 'Save', percent = '') { + const highlighSaving = document.createElement('span'); + highlighSaving.setAttribute('data-store-text-variable', ''); + highlighSaving.textContent = `${text} ${ + percent.toLowerCase() === 'percent' ? '{DISCOUNT_PERCENTAGE}' : '{DISCOUNT_VALUE}' + }`; + + const root = createTag( + 'div', + { + 'data-store-hide': 'no-price=discounted;type=visibility', + class: 'highlight await-loader', + style: 'display=none', + }, + `${highlighSaving.outerHTML}`, + ); + + return root; +} + +/** + * Nanoblock representing a text to highlight in the product card + * @param text Text to display + * @returns Root node of the nanoblock + */ +function renderHighlight(text) { + return createTag( + 'div', + { + class: 'highlight', + style: 'visibility:hidden', + }, + `${text}`, + ); +} + +/** + * + * @param {string} text Text of the featured nanoblock + * @return {string} Text with variables replaced + */ +const replaceVariablesInText = (text) => { + let replacedText = text; + + // replace the percent variable with correct percentage of the produc + TEXT_VARIABLES_MAPPING.forEach((textVariableMapping) => { + replacedText = replacedText.replaceAll( + textVariableMapping.variable, + textVariableMapping.storeVariable, + ); + }); + + return replacedText; +}; + +/** + * + * @param {string} text + * @return {boolean} wether the text contains variables or not + */ +const checkIfTextContainsVariables = (text) => TEXT_VARIABLES_MAPPING.some( + (textVariableMapping) => text.includes(textVariableMapping.variable), +); + +/** + * Nanoblock representing a text to Featured + * @param text Text of the featured nanoblock + * @returns Root node of the nanoblock + */ +function renderFeatured(text) { + const root = document.createElement('div'); + root.setAttribute('data-store-text-variable', ''); + root.classList.add('featured'); + root.textContent = text; + + if (checkIfTextContainsVariables(text)) { + root.classList.add('await-loader'); + root.textContent = replaceVariablesInText(root.textContent); + } + + return root; +} + +/** + * Nanoblock representing a text to Featured and the corresponding savings + * @param text Text of the featured nanoblock + * @param percent Show the saving in percentage if equals to `percent` + * @returns Root node of the nanoblock + */ +function renderFeaturedSavings(text = 'Save', percent = '') { + const featuredSaving = document.createElement('span'); + featuredSaving.setAttribute('data-store-text-variable', ''); + featuredSaving.textContent = `${text} ${ + percent.toLowerCase() === 'percent' ? '{DISCOUNT_PERCENTAGE}' : '{DISCOUNT_VALUE}' + }`; + + const root = createTag( + 'div', + { + 'data-store-hide': 'no-price=discounted;type=visibility', + class: 'featured', + }, + `${featuredSaving.outerHTML}`, + ); + root.classList.add('await-loader'); + + return root; +} + +/** + * Nanoblock representing the lowest product price + * @returns root node of the nanoblock + */ +function renderLowestPrice(...params) { + const filteredParams = params.filter((paramValue) => paramValue && (typeof paramValue !== 'object')).slice(-2); + const text = filteredParams.length > 1 ? filteredParams[1] : filteredParams[0]; + const monthly = filteredParams.length > 1 ? filteredParams[0] : ''; + const root = document.createElement('p'); + const textArea = document.createElement('span'); + root.classList.add('await-loader'); + textArea.setAttribute('data-store-text-variable', ''); + textArea.textContent = text.replace('0', monthly.toLowerCase() === 'monthly' ? '{SMALLEST_PRICE_PER_MONTH}' : '{SMALLEST_PRICE}'); + root.appendChild(textArea); + return root; +} + +/** + * Nanoblock representing the price conditions below the Price + * @param text Conditions + * @returns Root node of the nanoblock + */ +function renderPriceCondition(text) { + const updatedText = text.replace('BilledPrice', ''); + return createTag( + 'div', + { + class: 'price condition', + }, + `${updatedText}`, + ); +} + +// declare nanoblocks +createNanoBlock('plans', renderPlanSelector); +createNanoBlock('price', renderPrice); +createNanoBlock('oldPrice', renderOldPrice); +createNanoBlock('priceCondition', renderPriceCondition); +createNanoBlock('featured', renderFeatured); +createNanoBlock('featuredSavings', renderFeaturedSavings); +createNanoBlock('highlightSavings', renderHighlightSavings); +createNanoBlock('highlight', renderHighlight); +createNanoBlock('lowestPrice', renderLowestPrice); + +/** + * Main decorate function + */ +export default function decorate(block) { + const metadata = block.closest('.section').dataset; + const plans = []; + + Object.entries(metadata).forEach(([key, value]) => { + if (key.includes('plans')) { + const allImportantData = value.match(/[^,{}[\]]+/gu).map((importantData) => importantData.trim()); + plans.push({ + productCode: allImportantData[1], + defaultVariant: `${Number(allImportantData.slice(-1)[0]) + ? allImportantData.slice(-1)[0] : allImportantData[2].match(/[0-9-]+/g)[0] + }${allImportantData[2].match(/[0-9-]+/g)[1]}`, + }); + } + }); + + block.parentElement.parentElement.setAttribute('data-store-context', ''); + [...block.children].forEach((row, idxParent) => { + [...(row.children)].forEach((col, idxCol) => { + const plansIndex = idxParent * row.children.length + idxCol; + + // set the store event on the component + let storeEvent = 'main-product-loaded'; + if (checkIfConsumerPage()) { + storeEvent = 'product-loaded'; + } + + col.classList.add('product-card'); + col.setAttribute('data-store-context', ''); + if (plans[plansIndex]) { + col.setAttribute('data-store-id', plans[plansIndex].productCode); + col.setAttribute('data-store-option', plans[plansIndex].defaultVariant); + } + col.setAttribute('data-store-department', 'consumer'); + col.setAttribute('data-store-event', storeEvent); + const cardButtons = col.querySelectorAll('.button-container a'); + cardButtons?.forEach((button) => { + if (button.href?.includes('/buy/') || button.href?.includes('#buylink')) { + button.href = '#'; + button.setAttribute('data-store-buy-link', ''); + } + }); + block.appendChild(col); + renderNanoBlocks(col, undefined, idxParent); + }); + row.remove(); + }); + + // render nanoblocks in section's content default wrapper + const defaultContent = block.parentNode.parentNode.querySelector('.default-content-wrapper'); + if (defaultContent) { + renderNanoBlocks(defaultContent); + } + + // style the product card if the author has added a featured card inside + [...block.querySelectorAll('.product-card .featured')].forEach((featured) => { + featured.closest('.product-card').classList.add('featured'); + }); + + // add class to avoid using :has selector + block.querySelectorAll('.product-card li').forEach((li) => { + if (li.querySelector('del')) { + li.classList.add('with-del'); + } else { + li.classList.remove('with-del'); + } + }); + + block.querySelectorAll('.product-card ul').forEach((ul) => { + if (ul.previousElementSibling?.tagName === 'P') { + ul.previousElementSibling.classList.add('ul-header-text'); + } + }); + + block.querySelectorAll('.product-card ul li u').forEach((li) => { + li.parentNode.classList.add('icon-important'); + }); + + const paragraphs = block.querySelectorAll('.product-card.featured p'); + + // Iterate through each paragraph + paragraphs.forEach((paragraph) => { + // Check if the paragraph only contains span elements + const containsOnlySpans = Array.from(paragraph.childNodes).every((node) => node.nodeName === 'SPAN'); + + // If the paragraph only contains span elements, add a class + if (containsOnlySpans) { + paragraph.classList.add('os-availability'); + + if (paragraph.nextElementSibling.nodeName === 'P') { + paragraph.nextElementSibling.classList.add('os-availability-text'); + } + } + }); + + // Height matching and Dynamic texts logic + const cards = block.querySelectorAll('.product-card'); + const featuredCard = block.querySelector('.product-card.featured'); + cards.forEach((card, cardIndex) => { + const hasImage = card.querySelector('img') !== null; + if (hasImage && !block.classList.contains('plans') && !block.classList.contains('compact')) { + // If the image exists, set max-width to the paragraph next to the image + const firstPElement = card.querySelector('p:not(:has(img, .icon))'); + firstPElement.classList.add('img-adjacent-text'); + } + const planSelector = card.querySelector('.variant-selector'); + const dynamicPriceTextsKey = `dynamicPriceTexts${cardIndex + 1}`; + if (metadata[dynamicPriceTextsKey]) { + const dynamicPriceTexts = [...metadata[dynamicPriceTextsKey].split(',')]; + const priceConditionEl = card.querySelector('.price.condition em'); + planSelector?.querySelectorAll('li')?.forEach((option, idx) => { + option.addEventListener('click', () => { + if (option.classList.contains('active') && priceConditionEl && dynamicPriceTexts) { + const textTemplate = dynamicPriceTexts[idx] || ''; + // in order to preserve the store eventListeners we can't replace the priceElement + // every time another option is selected therefore we're using a string template + if (textTemplate.includes('{BilledPrice}')) { + const [before, after] = textTemplate.split('{BilledPrice}'); + const nodesToRemove = Array.from(priceConditionEl.childNodes).filter( + (node) => node.nodeType === Node.TEXT_NODE, + ); + // Clear only non- text nodes (this element contains store events) + nodesToRemove.forEach((node) => priceConditionEl.removeChild(node)); + // eslint-disable-next-line max-len + if (before) priceConditionEl.insertBefore(document.createTextNode(before), priceConditionEl.firstChild); + if (after) priceConditionEl.appendChild(document.createTextNode(after)); + } else { + priceConditionEl.textContent = textTemplate; + } + } + }); + }); + } + if (!card.classList.contains('featured')) { + // If there is no featured card, do nothing + if (!featuredCard) { + return; + } + let space = card.querySelector('h3'); + space = space.nextElementSibling; + const emptyDiv = document.createElement('div'); + space.insertAdjacentElement('afterend', emptyDiv); + emptyDiv.classList.add('featured', 'nanoblock'); + emptyDiv.style.visibility = 'hidden'; + } + }); + matchHeights(block, '.price.nanoblock:not(:last-of-type)'); + matchHeights(block, '.price.condition'); + matchHeights(block, 'h3:nth-of-type(2)'); + matchHeights(block, 'p:nth-of-type(2)'); + matchHeights(block, 'p:nth-of-type(3)'); + matchHeights(block, 'h4'); + matchHeights(block, 'ul:not(.variant-selector)'); + matchHeights(block, '.featured.nanoblock'); +} diff --git a/_src/blocks/questions-answers/questions-answers.css b/_src/blocks/questions-answers/questions-answers.css new file mode 100644 index 000000000..6a7256a78 --- /dev/null +++ b/_src/blocks/questions-answers/questions-answers.css @@ -0,0 +1,202 @@ +.questions-answers-wrapper { + padding: var(--body-padding); +} + +@media (min-width: 992px) { /* desktop */ + .questions-answers-wrapper { + max-width: 1330px; + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +.qa-creators.questions-answers-container h3 { + text-align: center; + font: bold 60px/69px "IBM Plex Sans", sans-serif; + margin-bottom: 32px; +} + +.questions-answers-container h4 { + text-align: center; + font: normal normal bold 32px/28px var(--body-font-family); + margin-bottom: 32px; +} + +.qa-creators.questions-answers-container h4 { + text-align: center; + font: bold 24px/26px "IBM Plex Sans", sans-serif; + margin-bottom: 32px; +} + +.questions-answers-container .default-content-wrapper p { + font: italic normal normal 14px/16px var(--body-font-family); +} + +.questions-answers-container .questions-answers-item .question h3 { + position: relative; + font: normal normal bold 18px / 21px var(--body-font-family) !important; + color: #000; + display: flex; + justify-content: space-between; + align-items: center; + padding-right: 25px; + margin-bottom: 0; +} + +.questions-answers-container .questions-answers-item.expanded .question h3 { + color: #006EFF; +} + +.questions-answers .questions-answers-item { + margin: 16px 0; + padding: 16px 16px 16px 40px; + background-color: #F4F8FF; + border-radius: 10px; + border-color: rgb(229 231 235); + border-width: 0; + display: flex; + flex-direction: column; + cursor: pointer; +} + +.questions-answers .questions-answers-item.expanded { + box-shadow: 0 3px 8px 0 rgb(0 0 0 / 10%); +} + +.questions-answers-item .question { + position: relative; + font: normal normal bold 18px/21px var(--body-font-family); + color: #000; + display: flex; + justify-content: space-between; + align-items: center; + padding-right: 25px; +} + +.qa-creators .questions-answers-item .question h4 { + position: relative; + font: normal normal bold 18px/21px var(--body-font-family); + color: #000; + display: flex; + justify-content: space-between; + align-items: center; + padding: 0; + margin: 0; + text-align: left; +} + +.questions-answers-item .question::before { + position: absolute; + font: normal normal normal 24px/11px var(--body-font-family); + content: url("/_src/icons/plus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: block; + left: -24px; + bottom:0; + top:3px; + margin-right: 10px; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.questions-answers-item.expanded .question { + color: #006EFF; +} + +.questions-answers-item.expanded .question::before { + font: normal normal normal 24px/11px var(--body-font-family); + top: 3px; + content: url("/_src/icons/minus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: inline-block; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.questions-answers-item .answer { + opacity: 0; + height: 0; + overflow: hidden; + transition: all 0.3s ease-in-out; +} + +.questions-answers-item .answer p { + font: normal normal normal 14px/16px var(--body-font-family); +} + +.questions-answers-item .answer p a { + color: #006EFF; +} + +.qa-creators.questions-answers-container .default-content-wrapper p { + font: bold 24px / 26px "IBM Plex Sans", sans-serif; + margin-bottom: 32px; + text-align: center; +} + +.questions-answers-item.expanded .answer { + opacity: 1; + height: auto; + transition: all 0.3s ease-in-out; +} + +.questions-answers-item.questions-answers-item-open .answer { + display: block; +} + +.questions-answers-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + margin: 0 auto; +} + +@media (max-width: 991px) { + .questions-answers-container h4 { + font: normal normal bold 29px / 28px var(--body-font-family); + margin: 0; + } + + .qa-creators.questions-answers-container h3 { + font-size: var(--heading-font-size-l); + line-height: 1.2; + font-family: "IBM Plex Sans", sans-serif; + font-weight: 300; + } + + .qa-creators.questions-answers-container h4 { + margin-bottom: 0; + font-weight: 300; + font-family: "IBM Plex Sans", sans-serif; + } +} + +@media (min-width: 992px) { /* desktop */ + .questions-answers-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .default-content-wrapper { + max-width: var(--section-desktop-max-width); + padding: 23px var(--section-desktop-padding); + border-radius: 0; + } +} + +@media (min-width: 1200px) { + .questions-answers-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .questions-answers-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/questions-answers/questions-answers.js b/_src/blocks/questions-answers/questions-answers.js new file mode 100644 index 000000000..b930ed02a --- /dev/null +++ b/_src/blocks/questions-answers/questions-answers.js @@ -0,0 +1,71 @@ +function expandItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + const transitionEndCallback = () => { + content.removeEventListener('transitionend', transitionEndCallback); + content.style.height = 'auto'; + }; + content.addEventListener('transitionend', transitionEndCallback); + item.classList.add('expanded'); +} + +function collapseItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + requestAnimationFrame(() => { + item.classList.remove('expanded'); + content.style.height = 0; + }); +} + +function handleAccordionItemClick(item, items) { + if (!item.classList.contains('expanded')) { + items.filter((i) => i.classList.contains('expanded')).forEach((i) => collapseItem(i)); + expandItem(item); + } else { + collapseItem(item); + } +} + +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + const items = Array.from(block.querySelectorAll(':scope > div')); + items.forEach((item) => { + item.classList.add('questions-answers-item'); + const [header, content] = item.children; + header.classList.add('question'); + + if (content) { + content.classList.add('answer'); + // check if .accordion-item-content has a

      + const p = content.querySelector('p'); + // if it doesn't, add a

      and move the content inside + if (!p) { + const newP = document.createElement('p'); + newP.innerHTML = content.innerHTML; + content.innerHTML = ''; + content.appendChild(newP); + } + } + + if ([...block.classList].includes('action-only-on-header')) { + header.addEventListener('click', handleAccordionItemClick.bind(null, header.parentElement, items)); + } else { + item.addEventListener('click', handleAccordionItemClick.bind(null, item, items)); + } + }); + + if (block.classList.contains('first-open')) { + items[0].classList.add('expanded'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/quiz-hero/quiz-hero.css b/_src/blocks/quiz-hero/quiz-hero.css new file mode 100644 index 000000000..acb18cbd4 --- /dev/null +++ b/_src/blocks/quiz-hero/quiz-hero.css @@ -0,0 +1,118 @@ +.quiz-hero-container.section { + padding: 0; +} + +.quiz-hero-container .quiz-hero-wrapper .block { + display: flex; + flex-direction: column; +} + +.quiz-hero-container h1 { + font: normal normal normal 32px/40px "IBM Plex Sans", sans-serif; +} + +.quiz-hero-container h2, +.quiz-hero-container h3, +.quiz-hero-container h4 { + font: normal normal normal 20px/23px Arial, sans-serif; +} + +.quiz-hero-container p, +.quiz-hero-container div { + font: normal normal normal 14px/18px Arial, sans-serif; +} + +.quiz-hero-container .rte-wrapper { + position: relative; + z-index: 4; + background-color: #006EFF; +} + +.quiz-hero-container .img-container { + width: 100%; + min-height: 250px; + height: 60vw; + position: relative; +} + +.quiz-hero-container .default-content-wrapper { + padding-top: 20px !important; + z-index: 4; + background-color: #006EFF; + color: white; +} + +.quiz-hero-container a.button:any-link { + border: solid white 2px !important; + background-color: white; + color: #006EFF; + margin-top: 15px; +} + +@media (min-width: 768px) { + .quiz-hero-container .img-container { + height: 470px; + } +} + +@media (min-width: 992px) { + .quiz-hero-container.section { + margin-top: 40px; + } + + .quiz-hero-container h1 { + font: normal normal normal 60px/66px "IBM Plex Sans", sans-serif; + } + + .quiz-hero-container h2, + .quiz-hero-container h3, + .quiz-hero-container h4 { + font: normal normal normal 32px/37px Arial, sans-serif; + } + + .quiz-hero-container p, + .quiz-hero-container div { + font: normal normal normal 18px/25px Arial, sans-serif; + } + + .quiz-hero-container { + height: 670px; + } + + .quiz-hero-container .quiz-hero-wrapper { + height: 100%; + } + + .quiz-hero-container .quiz-hero-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .quiz-hero-container .rte-wrapper { + width: 100%; + } + + .quiz-hero-container .img-container { + width: 100%; + height: 100%; + } + + .quiz-hero-container .default-content-wrapper { + padding-top: 0 !important; + order: unset; + position: absolute; + left: 0; + right: 0; + height: 100%; + display: flex; + align-items: center; + background-color: unset; + } + + .quiz-hero-container .default-content-wrapper > div { + width: 50%; + padding-right: 30px; + } +} + diff --git a/_src/blocks/quiz-hero/quiz-hero.js b/_src/blocks/quiz-hero/quiz-hero.js new file mode 100644 index 000000000..b1a6a50ae --- /dev/null +++ b/_src/blocks/quiz-hero/quiz-hero.js @@ -0,0 +1,15 @@ +import { adobeMcAppendVisitorId } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [rte, pictureEl] = [...block.children[0].children]; + + block.innerHTML = ` +

      +
      ${pictureEl.querySelector('picture').innerHTML}
      +
      + ${rte.outerHTML} +
      + `; + + adobeMcAppendVisitorId('header'); +} diff --git a/_src/blocks/quiz-result/quiz-result.css b/_src/blocks/quiz-result/quiz-result.css new file mode 100644 index 000000000..d6c45a82e --- /dev/null +++ b/_src/blocks/quiz-result/quiz-result.css @@ -0,0 +1,81 @@ +.quiz-result-container { + h3 { + font: normal normal bold 24px/27px Arial, sans-serif; + } + + h2 { + font: normal normal bold 32px/35px rial, sans-serif; + color: #006EFF; + } + + p, div { + font: normal normal normal 16px/18px rial, sans-serif; + } + + .results-wrapper { + position: relative; + box-shadow: 0 4px 13px 4px #0000003b; + border-radius: 20px; + padding: 10px 20px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + } + + .social-wrapper { + display: flex; + align-items: center; + font: normal normal bold 16px/18px rial, sans-serif; + color: #006EFF; + margin: 30px 0; + + a { + margin-left: 20px; + } + + .icon { + width: 20px; + height: 20px; + margin: 0; + } + } +} + +@media screen { + .quiz-result-container { + .results-wrapper { + background: url('/_src/images/quiz-results-bg.jpg') no-repeat; + } + } +} + +@media (min-width: 992px) { + .quiz-result-container { + .block > :first-child { + display: flex; + justify-content: center; + } + + h3 { + font: normal normal bold 24px/27px rial, sans-serif; + } + + h2 { + font: normal normal bold 42px/42px rial, sans-serif; + } + + p, div { + font: normal normal normal 18px/21px rial, sans-serif; + } + + .results-wrapper { + min-height: 600px; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + padding: 0 15%; + } + } +} diff --git a/_src/blocks/quiz-result/quiz-result.js b/_src/blocks/quiz-result/quiz-result.js new file mode 100644 index 000000000..df69fff77 --- /dev/null +++ b/_src/blocks/quiz-result/quiz-result.js @@ -0,0 +1,33 @@ +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const dataset = getDatasetFromSection(block); + + const { socialTitlePost } = dataset; + + block.classList.add('default-content-wrapper'); + block.children[0].children[0].classList.add('results-wrapper'); + block.children[0].children[0].lastElementChild.classList.add('social-wrapper'); + + const resultPageUrl = window.location.href; + + const socialWrapperEl = block.querySelector('.social-wrapper'); + [...socialWrapperEl.querySelectorAll('a')].forEach((anchor) => { + anchor.target = '_blank'; + anchor.rel = 'noopener noreferrer'; + + if (anchor.href.includes('twitter')) { + const twitterBaseUrl = 'https://twitter.com/intent/post?'; + const twitterText = `text=${encodeURIComponent(socialTitlePost)}`; + const twitterUrl = `&url=${encodeURIComponent(resultPageUrl)}`; + const fullTwitterUrl = twitterBaseUrl + twitterText + twitterUrl; + anchor.href = fullTwitterUrl; + } + if (anchor.href.includes('facebook')) { + const facebookBaseUrl = 'https://www.facebook.com/sharer/sharer.php?'; + const facebookUrl = `u=${encodeURIComponent(resultPageUrl)}`; + const fullFacebookUrl = facebookBaseUrl + facebookUrl; + anchor.href = fullFacebookUrl; + } + }); +} diff --git a/_src/blocks/quiz-stepper/quiz-stepper.css b/_src/blocks/quiz-stepper/quiz-stepper.css new file mode 100644 index 000000000..48b6731b1 --- /dev/null +++ b/_src/blocks/quiz-stepper/quiz-stepper.css @@ -0,0 +1,196 @@ +.quiz-stepper-container { + .block { + overflow: hidden; + padding-bottom: 200px; + } + + .slide-wrapper { + display: flex; + width: 100%; + transition: transform .250s ease-in-out; + padding: 5px 0; + } + + .form-wrapper { + width: 100%; + flex-shrink: 0; + margin-right: 60px; + } + + .step { + box-shadow: 0 3px 6px #00000029; + border-radius: 16px; + padding: 25px 30px calc(235px / 2 + 30px); + position: relative; + width: 100%; + flex-shrink: 0; + + fieldset { + legend { + text-align: left; + font: normal normal bold 18px/22px Arial, sans-serif; + color: #000; + margin-bottom: 20px; + } + + .error-message { + visibility: hidden; + color: red; + font-weight: 500; + } + + &.invalid { + .error-message { + visibility: visible; + } + } + } + + .img-container { + height: 235px; + border-radius: 30px; + overflow: hidden; + position: absolute; + bottom: calc(-235px / 2); + left: 25px; + right: 25px; + } + } + + .step-header { + display: flex; + align-items: center; + margin-bottom: 20px; + } + + .step-index { + padding: 3px 10px; + background: #E4F2FF 0% 0% no-repeat padding-box; + border-radius: 20px; + } + + .step-previous { + font: normal normal normal 12px/14px Arial, sans-serif; + color: #7E7E7E; + margin-left: auto; + position: relative; + display: flex; + align-items: center; + cursor: pointer; + + &::before { + content: ''; + display: block; + width: 20px; + height: 20px; + background: url('/_src/icons/arrow-right.svg') no-repeat; + opacity: 0.5; + transform: rotate(-180deg); + } + } + + .step-radio-wrapper { + display: flex; + align-items: flex-start; + margin-bottom: 13px; + cursor: pointer; + + input[type="radio"] { + display: block; + margin: 0; + padding: 0; + background-color: #fff; + font: inherit; + width: 16px; + height: 16px; + flex-shrink: 0; + } + + label { + font: normal normal normal 16px/18px Arial, sans-serif; + margin-left: 10px; + cursor: pointer; + } + + &.selected { + label { + font-weight: 600; + } + } + } + + .button-container.submit { + display: flex; + justify-content: center; + margin-top: 50px; + + .button { + background-color: #006EFF; + color: white; + border-radius: 5px; + padding: 16px; + width: 100%; + justify-content: center; + + &::after { + background-color: white; + } + } + } +} + +@media (min-width: 768px) { + .quiz-stepper-container { + .step { + height: 630px; + + .img-container { + height: 400px; + bottom: calc(-400px / 2); + } + } + } +} + +@media (min-width: 992px) { + .quiz-stepper-container { + .block { + padding-bottom: 0; + } + + .step { + height: unset; + width: calc(100% - 250px); + padding: 40px 40% 40px 40px; + + .img-container { + width: 500px; + height: 385px; + bottom: unset; + left: unset; + top: calc(50% - 385px / 2); + right: -250px; + } + + fieldset { + legend { + font: normal normal bold 22px/27px Arial, sans-serif; + margin-bottom: 30px; + } + + label { + font: normal normal normal 18px/21px Arial, sans-serif; + } + } + } + + .button-container.submit { + justify-content: flex-start; + margin-top: 30px; + + .button { + width: 60%; + } + } + } +} diff --git a/_src/blocks/quiz-stepper/quiz-stepper.js b/_src/blocks/quiz-stepper/quiz-stepper.js new file mode 100644 index 000000000..14d9a9718 --- /dev/null +++ b/_src/blocks/quiz-stepper/quiz-stepper.js @@ -0,0 +1,146 @@ +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const dataset = getDatasetFromSection(block); + + const { + questionLabel, nextButtonLabel, previousButtonLabel, seeResultsLabel, selectErrorLabel, + } = dataset; + + const state = { + score: 0, + currentStep: 0, + }; + + block.classList.add('default-content-wrapper'); + block.closest('.section').id = 'quiz-form'; + + const steps = [...block.children]; + + function renderStep(step, index) { + const stepTitle = step.children[0].children[0].textContent; + const stepOptions = [...step.children[0].children[1].children]; + const stepImage = step.children[1].children[0]; + const isFirstStep = index === 0; + const isLastStep = index === steps.length - 1; + + const fieldId = `question-${index}`; + + return ` +
      +
      +
      +
      ${questionLabel} ${index + 1}/${steps.length}:
      + ${!isFirstStep ? `${previousButtonLabel}` : ''} +
      + + +
      + ${stepTitle} + + + ${stepOptions.map((option, idx) => { + const value = option.querySelector('u') ? 1 : 0; + const forLabel = `${fieldId}-${idx}`; + + return ` +
      + + +
      + `; + }).join('')} +
      ${selectErrorLabel}
      +
      + +

      + ${!isLastStep ? nextButtonLabel : seeResultsLabel} +

      + +
      + ${stepImage.outerHTML} +
      +
      +
      + `; + } + + function moveToNextStep() { + state.currentStep += 1; + const slideWrapper = block.querySelector('.slide-wrapper'); + const offset = 60; + + const transformValue = `translateX(calc(-100% * ${state.currentStep} - (${offset}px * ${state.currentStep})))`; + slideWrapper.style.transform = transformValue; + } + + function moveToPreviousStep() { + state.currentStep -= 1; + const slideWrapper = block.querySelector('.slide-wrapper'); + const offset = 60; + + const transformValue = `translateX(calc(-100% * ${state.currentStep} - (${offset}px * ${state.currentStep})))`; + slideWrapper.style.transform = transformValue; + } + + function renderResults() { + block.style.transform = null; + + // get score + /* eslint-disable-next-line */ + const score = [...block.querySelectorAll('input[type="radio"]:checked')].map((inputEl) => inputEl.value).reduce((sc, value) => sc += Number(value), 0); + + const legendScore = Object.keys(dataset) + .filter((item) => item.includes('result_')) + .map((item) => ({ + template: item.split('result_')[1].split('_').join('-'), + interval: [...dataset[item].split('-')], + })); + + /* eslint-disable max-len */ + const foundLegend = legendScore.find(({ interval: [min, max] }) => Number(min) <= score && score <= Number(max)); + + const { origin, pathname } = window.location; + // redirect + window.location.replace(`${origin}${pathname}${foundLegend.template}`); + } + + function validateForm(e) { + e.preventDefault(); + + const formEl = e.target.closest('form'); + const selectedOption = formEl.querySelector('input[type="radio"]:checked'); + const isLastStep = state.currentStep === steps.length - 1; + + if (!selectedOption) { + formEl.querySelector('fieldset').classList.add('invalid'); + return; + } + + if (!isLastStep) { + moveToNextStep(); + return; + } + + renderResults(); + } + + block.innerHTML = ` +
      ${steps.map((step, index) => renderStep(step, index)).join('')}
      + `; + + block.querySelectorAll('form').forEach((form) => { + const radios = form.querySelectorAll('input[type="radio"]'); + + radios.forEach((radio) => { + radio.addEventListener('change', (event) => { + if (event.target.checked) { + form.querySelector('fieldset').classList.remove('invalid'); + } + }); + }); + + form.querySelectorAll('.button-container.submit').forEach((buttonEl) => buttonEl.addEventListener('click', validateForm)); + form.querySelectorAll('.step-previous').forEach((previousEl) => previousEl.addEventListener('click', moveToPreviousStep)); + }); +} diff --git a/solutions/blocks/quote-carousel/quote-carousel.css b/_src/blocks/quote-carousel/quote-carousel.css similarity index 91% rename from solutions/blocks/quote-carousel/quote-carousel.css rename to _src/blocks/quote-carousel/quote-carousel.css index 48f1c39c5..7a51c8b53 100644 --- a/solutions/blocks/quote-carousel/quote-carousel.css +++ b/_src/blocks/quote-carousel/quote-carousel.css @@ -5,7 +5,8 @@ main .quote-carousel { main .quote-carousel .slides-container { border-radius: 8px; - max-width: 630px; + max-width: auto; + width: 100%; margin-bottom: 30px; box-shadow: 0 3px 8px 0 rgb(0 0 0 / 10%); background: var(--background-color); @@ -30,11 +31,12 @@ main .quote-carousel .slides-container { @media (min-width: 992px) { main .quote-carousel { - max-width: 90%; + max-width: 100%; margin: 55px 0 0; } main .quote-carousel .slides-container { + max-width: 590px; margin-bottom: 80px; } } @@ -59,7 +61,7 @@ main .quote-carousel .slides-container { flex-shrink: 0; width: 100%; transition: all 0.3s ease-in-out; - padding: 30px 30px 40px 25px; + padding: 2em 2em 1em; gap: 8px; } @@ -68,6 +70,10 @@ main .quote-carousel .slides-container { gap: 8px; padding-left: 30px; } + + main .quote-carousel .slides-container { + max-width: 630px; + } } .slide .icon { @@ -134,6 +140,10 @@ main .quote-carousel .slides-container { padding-top: 16px; } +.slides-container .slide p:last-of-type { + padding-top: 5px; +} + @media (min-width: 768px) { .slides-container .slide p { line-height: 1.25; @@ -162,7 +172,7 @@ main .quote-carousel .slides-container { align-self: flex-start; display: flex; list-style: none; - gap: 16px; + gap: 8px; } .slides-container .slides-dots li { @@ -202,3 +212,9 @@ main .quote-carousel .slides-container { .slides-container .slides-dots li:hover button { background: #006eff; } + +@media (max-width: 992px) { + main .quote-carousel { + margin-top: 0; + } +} \ No newline at end of file diff --git a/solutions/blocks/quote-carousel/quote-carousel.js b/_src/blocks/quote-carousel/quote-carousel.js similarity index 98% rename from solutions/blocks/quote-carousel/quote-carousel.js rename to _src/blocks/quote-carousel/quote-carousel.js index 350afa44d..e6c758b96 100644 --- a/solutions/blocks/quote-carousel/quote-carousel.js +++ b/_src/blocks/quote-carousel/quote-carousel.js @@ -1,4 +1,4 @@ -import { createTag } from '../../scripts/utils.js'; +import { createTag } from '../../scripts/utils/utils.js'; import { decorateIcons } from '../../scripts/lib-franklin.js'; const SLIDE_PREFIX = 'carousel-slide-'; diff --git a/solutions/blocks/quote/quote.css b/_src/blocks/quote/quote.css similarity index 100% rename from solutions/blocks/quote/quote.css rename to _src/blocks/quote/quote.css diff --git a/solutions/blocks/quote/quote.js b/_src/blocks/quote/quote.js similarity index 96% rename from solutions/blocks/quote/quote.js rename to _src/blocks/quote/quote.js index beba25c50..fd176c411 100644 --- a/solutions/blocks/quote/quote.js +++ b/_src/blocks/quote/quote.js @@ -1,4 +1,4 @@ -import { createTag } from '../../scripts/utils.js'; +import { createTag } from '../../scripts/utils/utils.js'; import { decorateIcons } from '../../scripts/lib-franklin.js'; function createQuote(item) { diff --git a/_src/blocks/ribbon/ribbon.css b/_src/blocks/ribbon/ribbon.css new file mode 100644 index 000000000..a8279147f --- /dev/null +++ b/_src/blocks/ribbon/ribbon.css @@ -0,0 +1,38 @@ +main .ribbon-container { + color: white; + text-align: center; + background-position: 0 -18px; + background-repeat: repeat; + background-blend-mode: unset; + background-color: black; + padding-top: 20px; + padding-bottom: 20px; +} + +.ribbon-container * { + font-family: Arial, sans-serif!important; + font-size: var(--body-font-size-xs); +} + +.ribbon-container p { + text-align: center; + margin: 5px 0; +} + +.ribbon-container img { + width: 27px; + float: left; +} + +.ribbon-container a:any-link { + color: inherit; + text-decoration: underline; +} + +.ribbon-container .block > div > div { + display: flex; + justify-content: center; + align-items: center; + gap: 10px; + text-shadow: 0 0 34px #f00, 0 0 34px #f00, 0 0 34px #f00, 0 0 34px #f00, 0 0 34px #f00; +} \ No newline at end of file diff --git a/_src/blocks/ribbon/ribbon.js b/_src/blocks/ribbon/ribbon.js new file mode 100644 index 000000000..d2e99164b --- /dev/null +++ b/_src/blocks/ribbon/ribbon.js @@ -0,0 +1,14 @@ +export default function decorate(block) { + const [, backgroundEl] = block.children; + + if (backgroundEl) { + const backgroundImgEl = backgroundEl.querySelector('img'); + const backgroundImgSrc = backgroundImgEl?.getAttribute('src'); + + if (backgroundImgSrc) { + block.closest('.section').style.backgroundImage = `url("${backgroundImgSrc}")`; + // Remove the row after setting background + backgroundEl.remove(); + } + } +} diff --git a/_src/blocks/round-card/round-card.css b/_src/blocks/round-card/round-card.css new file mode 100644 index 000000000..a5806dfb9 --- /dev/null +++ b/_src/blocks/round-card/round-card.css @@ -0,0 +1,87 @@ +main .section.round-card-container.mt-n60 { + padding-top: 0; + margin-top: -60px; +} + +.round-card-container .inner-wrapper { + display: flex; + background-color: #fff; + border-radius: 8px; + box-shadow: 0 3px 6px 0 rgb(0 0 0 / 8%); + position: relative; + overflow: hidden; + z-index: 2; + width: 100%; + margin: 10px 0; + padding: 40px 23px 2pc; +} + +/* first paragraph */ +.round-card-container .inner-wrapper > div:nth-child(2) > p:nth-child(3) { + margin-top: 40px; +} + +.round-card-container .inner-wrapper > div:last-child { + border-radius: 50%; + position: absolute; + right: -35px; + top: -60px; + width: 225px; + height: 225px; + overflow: hidden; +} + +.round-card-container img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform .3s ease-in-out,-webkit-transform .3s ease-in-out; + transform: scale(1); +} + +.round-card-container .inner-wrapper > a:first-child { + position: absolute; + top: 0; + left: 0; + z-index: 2; + width: 100%; + height: 100%; + text-indent: -999999px; +} + +.round-card-container .inner-wrapper > div:nth-child(2) > * { + max-width: 150px; +} + +@media(min-width: 767px) { + /* tablet */ + .round-card-container .inner-wrapper > div:nth-child(2) { + max-width: calc(100% - 280px); + } + + .round-card-container .inner-wrapper > div:nth-child(2) > * { + max-width: unset; + } + + .round-card-container .inner-wrapper p { + font-size: 18px; + } + + .round-card-container .inner-wrapper > div:last-child { + width: 285px; + height: 285px; + } + + .round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a::after { + transform: translateX(5px); + opacity: 1; + } + + .round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a span.button-text { + transform: translate(-10px, 0); + } + + .round-card-container .inner-wrapper > a:first-child:hover ~ div img { + transform: scale(1.1); + } +} diff --git a/_src/blocks/round-card/round-card.js b/_src/blocks/round-card/round-card.js new file mode 100644 index 000000000..3a4b35a2e --- /dev/null +++ b/_src/blocks/round-card/round-card.js @@ -0,0 +1,15 @@ +export default function decorate(block) { + const innerWrapper = block.children[0]; + innerWrapper.classList = 'inner-wrapper'; + + const originalAnchorEl = innerWrapper.children[0].lastElementChild.firstElementChild; + const newAnchorEl = originalAnchorEl.cloneNode(); + newAnchorEl.classList = ''; + innerWrapper.prepend(newAnchorEl); + + const defaultWrapper = document.createElement('div'); + defaultWrapper.classList = 'default-content-wrapper'; + + defaultWrapper.append(innerWrapper); + block.prepend(defaultWrapper); +} diff --git a/_src/blocks/scuderia-ferrari-section/scuderia-ferrari-section.css b/_src/blocks/scuderia-ferrari-section/scuderia-ferrari-section.css new file mode 100644 index 000000000..42517ddd2 --- /dev/null +++ b/_src/blocks/scuderia-ferrari-section/scuderia-ferrari-section.css @@ -0,0 +1,524 @@ +main .scuderia-ferrari-section-container, main .scuderia-ferrari-section-wrapper{ + margin: 0; + padding: 0; +} + +.scuderia-ferrari-section{ + display: flex; + align-items: center; + background-color: #006EFF; + padding: 20px; + color: #fff; + + img{ + display: none; + } +} + +.scuderia-ferrari-section.quotes-right, .scuderia-ferrari-section.quotes-left { + > div { + display: flex; + flex-flow: column; + justify-content: center; + z-index: 1; + padding: 0; + } + + p { + font-size: 24px; + + strong { + font-size: 16px; + } + + &:last-of-type { + line-height: 1.23; + font-size: 12px; + } + } + + img { + display: block; + position: absolute; + top: 0; + bottom: auto; + left: 0; + right: 0; + height: 100%; + width: 100%; + object-fit: cover; + z-index: 0; + } + + h2 { + line-height: 0.66; + } + + div { + padding: 10px; + + &:last-of-type { + max-width: 80%; + } + } +} + +.scuderia-ferrari-section.quotes-left { + width: 100%; + background-color: #FF2800; + padding: 20px; + flex-flow: column; + display: flex; + align-items: baseline; + text-align: left; +} + +.scuderia-ferrari-section.quotes-right { + width: 100%; + background-color: #FF2800; + padding: 20px; + flex-flow: column; + display: inline-flex; + text-align: right; + align-items: end; + justify-content: right; + + div:last-of-type { + align-items: end; + } + + p:nth-last-of-type(2) { + line-height: 1.23; + font-size: 12px; + } +} + +.scuderia-ferrari-section.video-block{ + display: flex; + justify-content: center; + align-items: center; + flex-flow: column; + background-color: #fff; + color: #006EFF; + text-align: center; + padding: 20px; + margin-bottom: 40px; + margin-top: 0; + + h2{ + font-size: 24px; + font-weight: 300; + } + + div:first-child{ + min-width: 100%; + justify-items: center; + } + + .video-container{ + width: 100%; + } + + .video-container iframe{ + width: 100%; + min-height: 225px; + border-radius: 20px; + } +} + + + +.scuderia-ferrari-section.image-right{ + padding: 20px; + background-color: #F4FAFF; + color: #000; + + h2{ + color: #006EFF; + } +} + +@media (min-width: 767px){ + .scuderia-ferrari-section{ + padding:5%; + + h3{ + font-size: 40px; + } + + p{ + font-size: 26px; + } + + div:first-child{ + display: flex; + flex-flow: column; + } + } + + .scuderia-ferrari-section.video-block{ + padding:5%; + + h2{ + line-height: 1; + font-size: 44px; + margin-bottom: 60px; + } + + .video-container{ + border-radius: 20px; + width: 100%; + height: 80%; + } + + .video-container iframe{ + border-radius: 20px; + min-height: 450px; + width: 100%; + padding: 0; + } + } + + .scuderia-ferrari-section.image-right{ + padding: 5%; + background-color: #F4FAFF; + color: #000; + + h2{ + font-size: 32px; + } + + h3{ + font-size: 44px; + } + + p strong{ + font-size: 22px; + } + + p{ + font-size: 16px; + } + + div{ + display: flex; + flex-direction: column; + align-items: flex-start; + } + + div:first-child{ + min-width: 100%; + } + + img{ + display: none; + } + } + + .scuderia-ferrari-section.quotes-right, .scuderia-ferrari-section.quotes-left{ + flex-flow: unset; + min-height: 900px; + padding: 0; + + p{ + color: white; + z-index: 1; + position: relative; + font-weight: 300; + font-size: 44px; + margin: 0; + } + + p strong{ + font-size: 22px; + font-weight: 700; + } + + p:last-of-type{ + font-size: 26px; + font-weight: 400; + } + + h2{ + color: #fff; + font-size: 96px; + font-weight: 700; + margin: 0; + } + } + + .scuderia-ferrari-section.quotes-left{ + align-items: end; + + div:last-of-type{ + padding-bottom: 50px; + } + } + + .scuderia-ferrari-section.quotes-right{ + p:nth-last-of-type(2){ + font-size: 26px; + font-weight: 400; + } + + > div:last-of-type{ + align-self: center; + } + + div:last-of-type{ + padding: 5%; + max-width: 80%; + } + } +} + +@media (min-width:1020px){ + .scuderia-ferrari-section{ + padding: 5%; + + div:first-child{ + max-width: 80%; + } + + div:last-of-type{ + max-width: 80%; + } + + img{ + display: block; + position: absolute; + object-fit: cover; + top: 5%; + bottom: 0; + right: 0; + width: auto; + height: 90%; + z-index: 0; + } + } + + .scuderia-ferrari-section.image-right{ + padding: 5%; + + img{ + display: block; + top:10%; + right: 8%; + min-height: 80%; + height: auto; + object-position: center; + border-radius: 40px; + z-index: 0; + max-width: 40%; + } + + div:first-child{ + min-width: auto; + max-width: 70%; + } + } + + .scuderia-ferrari-section.video-block{ + div:last-of-type { + max-width: 100%; + } + } +} + +@media (min-width: 1200px){ + .scuderia-ferrari-section{ + padding:7% 10%; + + h2{ + font-size: 36px; + } + + h3{ + font-size: 48px; + } + + p{ + font-size: 22px; + } + } + + .scuderia-ferrari-section.video-block{ + padding:5% 10%; + + h2{ + font-size: 54px; + } + + .video-container iframe{ + min-height: 600px; + } + } + + .scuderia-ferrari-section.quotes-right, .scuderia-ferrari-section.quotes-left{ + p{ + font-size: 54px; + } + + p strong{ + font-size: 22px; + } + + div:last-of-type{ + padding: 5%; + } + } + + .scuderia-ferrari-section.quotes-left{ + div:last-of-type{ + max-width: 80%; + padding-bottom: 50px; + } + } + + .scuderia-ferrari-section.image-right{ + padding: 10%; + + div:first-child{ + padding: 0; + padding-right: 2%; + max-width: 75%; + } + + h2{ + font-size: 36px; + } + + h3{ + font-size: 44px; + } + + p strong{ + font-size: 28px; + } + + p{ + font-size: 24px; + } + + img{ + max-width: 35%; + } + + a.button.primary{ + font-size: 23px; + padding: 15px 29px; + } + + a.button span.button-text{ + margin-left: 14px; + } + } +} + +@media (min-width: 1400px){ + .scuderia-ferrari-section.quotes-left{ + padding-top: 15%; + padding-bottom: 5%; + } +} + +@media (min-width:1750px){ + .scuderia-ferrari-section{ + padding: 5% 15%; + + h2{ + font-size: 42px; + } + + h3{ + font-size: 54px; + } + + p{ + font-size: 26px; + } + + img{ + right: 0; + } + } + + .scuderia-ferrari-section.image-right{ + padding:7% 15%; + + img{ + position: static; + height: 1000px; + min-width: 655px; + border-radius: 40px; + } + + + h2{ + font-size: 42px; + } + + h3{ + font-size: 54px; + } + + p strong{ + font-size: 32px; + } + + p{ + font-size: 26px; + } + + div:first-child{ + max-width: 90%; + padding-right: 0; + } + } + + .scuderia-ferrari-section.video-block{ + padding:7% 15%; + + .video-container iframe{ + min-height: 715px; + } + + h2{ + font-size: 64px; + } + } + + .scuderia-ferrari-section.quotes-right{ + padding:10% 15%; + + p{ + font-size: 64px; + } + + p strong{ + font-size: 26px; + } + + div:last-of-type { + max-width: 70%; + padding: 0; + } + } + + .scuderia-ferrari-section.quotes-left{ + padding: 25% 15% 5%; + + p{ + font-size: 64px; + } + + p strong{ + font-size: 26px; + } + + div:last-of-type { + max-width: 70%; + padding: 0; + } + } +} \ No newline at end of file diff --git a/_src/blocks/scuderia-ferrari-section/scuderia-ferrari-section.js b/_src/blocks/scuderia-ferrari-section/scuderia-ferrari-section.js new file mode 100644 index 000000000..8deed47f6 --- /dev/null +++ b/_src/blocks/scuderia-ferrari-section/scuderia-ferrari-section.js @@ -0,0 +1,21 @@ +function replacePlaceholderWithVideo(videoUrl) { + const placeholderDiv = [...document.querySelectorAll('div')].find((div) => div.textContent.trim() === '{video}'); + if (!placeholderDiv) { + return; + } + const videoContainer = document.createElement('div'); + videoContainer.className = 'video-container'; + + const iframeElement = document.createElement('iframe'); + iframeElement.setAttribute('src', videoUrl); + iframeElement.setAttribute('frameborder', '0'); + iframeElement.setAttribute('allow', 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'); + iframeElement.setAttribute('allowfullscreen', ''); + videoContainer.appendChild(iframeElement); + placeholderDiv.replaceWith(videoContainer); +} + +export default function decorate(block) { + const { video } = block.closest('.section').dataset; + replacePlaceholderWithVideo(video); +} diff --git a/_src/blocks/spurs-hero/spurs-hero.css b/_src/blocks/spurs-hero/spurs-hero.css new file mode 100644 index 000000000..a0ab1b792 --- /dev/null +++ b/_src/blocks/spurs-hero/spurs-hero.css @@ -0,0 +1,181 @@ +.spurs-hero-container.section { + padding: 0; +} + +.spurs-hero-container .spurs-hero-wrapper .block { + display: flex; + flex-direction: column; +} + +.spurs-hero-container h1 { + font-size: 24px; + font-weight: 600; + line-height: 1.25; +} + +.spurs-hero-container.hero-ferrari h1 { + font-size: 29px; + line-height: 1.2; + font-weight: normal; +} + +.spurs-hero-container.hero-ferrari h2 { + font-size: 18px; + font-weight: normal; +} + +.spurs-hero-container p, +.spurs-hero-container div { + font-size: 16px; + font-weight: 500; + line-height: 1.6; +} + +.spurs-hero-container .rte-wrapper { + position: relative; + z-index: 4; + background-color: #006EFF; +} + +.spurs-hero-container .img-container { + display: none; + width: 100%; + height: 200px; + position: relative; +} + +.hero-ferrari .img-container { + display: block; + width: 100%; + height: 48vw; +} + +.spurs-hero-container .default-content-wrapper { + padding-top: 20px !important; + z-index: 4; + background-color: #006EFF; + color: white; +} + +.spurs-hero-container a.button:any-link { + border: solid white 2px !important; + background-color: white; + color: #006EFF; + margin-top: 15px; +} + +.spurs-hero-container .default-content-wrapper p.button-container a { + border: solid white 2px !important; + background-color: transparent; + color: white; + margin-top: 15px; +} + +.spurs-hero-container .default-content-wrapper p:not(.button-container):nth-last-child(2) { + position: relative; + margin-top: 80px; +} + +.spurs-hero-container .default-content-wrapper p:not(.button-container) img { + width: 90px; + position: absolute; + top: -45px; + left: 5px; +} + +.spurs-hero-container .default-content-wrapper p:not(.button-container) a { + background: white; + padding: 10px 16px 10px 100px; + font-size: 14px; + color: #006DFF; + font-weight: 600; + text-transform: none; + display: inline-block; + text-align: center; + border-radius: 8px; + transition: background-color 0.2s; + width: auto; + border-style: none; + cursor: pointer; +} + +@media (min-width: 992px) { + .spurs-hero-container h1 { + font-size: 40px; + font-weight: 300; + line-height: 1; + } + + .spurs-hero-container.hero-ferrari h1 { + font-size: 48px; + font-weight: 300; + line-height: 57px; + } + + .spurs-hero-container.hero-ferrari h2 { + font-size: 32px; + font-weight: 300; + } + + .spurs-hero-container p, + .spurs-hero-container div { + /* font: normal normal normal 18px/25px Arial; */ + font-size: 28px; + font-weight: 300; + line-height: 1.3; + } + + .spurs-hero-container { + height: 600px; + } + + .spurs-hero-container .spurs-hero-wrapper { + height: 100%; + } + + .spurs-hero-container .spurs-hero-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .spurs-hero-container .rte-wrapper { + width: 100%; + } + + .spurs-hero-container .default-content-wrapper { + padding-top: 0 !important; + order: unset; + position: absolute; + left: 0; + right: 0; + height: 100%; + display: flex; + align-items: center; + background-color: unset; + } + + .spurs-hero-container .default-content-wrapper > div { + width: 50%; + padding-top: 65px; + } + + .spurs-hero-container .img-container { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: #006EFF; + } + + .spurs-hero-container.hero-ferrari .img-container { + align-items: normal; + justify-content: left; + } + + .spurs-hero-container .img-container picture { + width: 90%; + } +} + diff --git a/_src/blocks/spurs-hero/spurs-hero.js b/_src/blocks/spurs-hero/spurs-hero.js new file mode 100644 index 000000000..cbbde9eee --- /dev/null +++ b/_src/blocks/spurs-hero/spurs-hero.js @@ -0,0 +1,24 @@ +import { adobeMcAppendVisitorId } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [rte, pictureEl] = [...block.children[0].children]; + + if (window.location.href.indexOf('scuderiaferrari') !== -1) { + block.closest('.section').classList.add('hero-ferrari'); + } + + block.innerHTML = ` +
      +
      ${pictureEl.querySelector('picture').outerHTML}
      +
      + ${rte.outerHTML} +
      + `; + + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); + + adobeMcAppendVisitorId('header'); +} diff --git a/solutions/blocks/sticky-navigation/sticky-navigation.css b/_src/blocks/sticky-navigation/sticky-navigation.css similarity index 84% rename from solutions/blocks/sticky-navigation/sticky-navigation.css rename to _src/blocks/sticky-navigation/sticky-navigation.css index 8260de001..5aa0abdc2 100644 --- a/solutions/blocks/sticky-navigation/sticky-navigation.css +++ b/_src/blocks/sticky-navigation/sticky-navigation.css @@ -4,6 +4,7 @@ main .section.sticky-navigation-container { padding-top: 0; + padding-bottom: 0; } .sticky-navigation { @@ -25,10 +26,10 @@ main .section.sticky-navigation-container { display: none; flex-direction: column; justify-content: center; - align-items: baseline; + align-items: center; box-shadow: 0 3px 6px 0 rgb(0 0 0 / 8%); padding: 0 var(--body-padding) var(--body-padding) var(--body-padding); - + } .sticky-navigation ul { @@ -39,6 +40,16 @@ main .section.sticky-navigation-container { list-style-type: none; } +.sticky-navigation ul li { + border-bottom: 1px solid var(--sticky-nav-border-color); + padding: 0; + margin: 0; +} + +.sticky-navigation ul li.opened { + border-bottom: 1px solid #006EFF; +} + .sticky-navigation ul li a { display: block; font-weight: var(--font-weight-bold); @@ -50,12 +61,6 @@ main .section.sticky-navigation-container { padding: 22px 0; } -.sticky-navigation ul li { - border-bottom: 1px solid var(--sticky-nav-border-color); - padding: 0; - margin: 0; -} - .sticky-navigation ul li.active::after { width: 100%; } @@ -111,13 +116,18 @@ main .section.sticky-navigation-container { .sticky-navigation .button-container { margin:0; - padding: 40px 0 20px 20px; + padding: 40px 0 20px 20px; } .sticky-navigation .button-container a { - font-size: var(--body-font-size-xxs); + font-size: var(--body-font-size-s); vertical-align: middle; - padding: 6px 15px; + padding: 6px 9px 6px 18px; + text-transform: capitalize; +} + +.sticky-navigation .button-container a .button-text{ + white-space: nowrap; } @media (min-width: 992px) { /* desktop */ @@ -142,7 +152,7 @@ main .section.sticky-navigation-container { .sticky-navigation ul li { border: none; - margin-right: 20px; + margin-right: 40px; } .sticky-navigation ul li a { @@ -157,19 +167,25 @@ main .section.sticky-navigation-container { .sticky-navigation .button-container { vertical-align: middle; - padding: 0; + padding: 0; + } +} + +@media (max-width: 1399px) { /* desktop */ + .sticky-navigation .menu-with-button { + padding: 0 var(--section-large-desktop-padding); } } @media (min-width: 1600px) { /* large desktop */ .sticky-navigation .button-container a { - font-size: var(--body-font-size-xs); - padding: 8px 15px; + font-size: var(--body-font-size-s); + font-weight: var(--font-weight-bold); + padding: 8px 8px 8px 20px; } .sticky-navigation .menu-with-button { max-width: var(--section-large-desktop-max-width); padding: 0 var(--section-large-desktop-padding); } - } \ No newline at end of file diff --git a/solutions/blocks/sticky-navigation/sticky-navigation.js b/_src/blocks/sticky-navigation/sticky-navigation.js similarity index 95% rename from solutions/blocks/sticky-navigation/sticky-navigation.js rename to _src/blocks/sticky-navigation/sticky-navigation.js index 2c8fbf64f..1b9a47428 100644 --- a/solutions/blocks/sticky-navigation/sticky-navigation.js +++ b/_src/blocks/sticky-navigation/sticky-navigation.js @@ -63,7 +63,11 @@ function renderStickyNavigation(block) { menuWithButton.appendChild(stickyNavMenu); /** close the dropdown menu after user selection */ - stickyNavMenu.addEventListener('click', () => { + stickyNavMenu.addEventListener('click', (event) => { + event.target.closest('ul').querySelectorAll('li').forEach((item) => { + item.classList.remove('opened'); + }); + event.target.closest('li').classList.toggle('opened'); mobileDropDown.classList.toggle('opened'); }); diff --git a/_src/blocks/system-requirements/system-requirements.css b/_src/blocks/system-requirements/system-requirements.css new file mode 100644 index 000000000..792e1831f --- /dev/null +++ b/_src/blocks/system-requirements/system-requirements.css @@ -0,0 +1,257 @@ +.system-requirements-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1290px; + --section-desktop-padding: 20px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); + + background-color: #f2f2f2; +} + +.system-requirements-wrapper { + padding: var(--body-padding); +} + +.default-content-wrapper { + width: 100%; + margin: 0 auto; + max-width: var(--body-max-width); + padding: var(--body-padding); + position: relative; +} + +.system-requirements-container h6 { + text-align: left; + font: normal normal bold 16px/18px var(--body-font-family); + margin: 0; +} + + +/* remove padding from userguide wrapper */ +.system-requirements-container :last-child { + padding-bottom: 1px; +} + +.system-requirements-container-userguides { + background-color: #f2f2f2; +} + +.system-requirements-container .default-content-wrapper p { + font: normal normal normal 12px/14px var(--body-font-family); +} + +.system-requirements-container .system-requirements-item { + padding: 8px 16px 8px 24px; + display: flex; + flex-direction: column; + cursor: pointer; +} + +.system-requirements-item .system { + position: relative; + font: normal normal bold 12px/14px var(--body-font-family); + color: #006EFF; + display: flex; + justify-content: space-between; + align-items: center; + padding-right: 25px; +} + +.system-requirements-item .system::before { + position: absolute; + font: normal normal normal 24px/11px var(--body-font-family); + content: url("/_src/icons/plus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: block; + left: -24px; + bottom:0; + top:-1px; + margin-right: 10px; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.system-requirements-item.expanded .system { + color: #006EFF; +} + +.system-requirements-item.expanded .system::before { + font: normal normal normal 24px/11px var(--body-font-family); + top: -1px; + content: url("/_src/icons/minus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: inline-block; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.system-requirements-item .requirement { + opacity: 0; + height: 0; + overflow: hidden; + transition: all 0.3s ease-in-out; +} + +.system-requirements-item .requirement > ul { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + grid-gap: 24px; +} + +.system-requirements-item .requirement > ul > li { + font: normal normal normal 12px/14px var(--body-font-family); + list-style: none; + display: inline-block; + padding-left: 0; +} + +.system-requirements-item .requirement > ul > li > br { + display: block; + margin-bottom: 14px; + content: " "; +} + +.system-requirements-item .requirement > ul > li > br:first-of-type { + margin: 0; +} + +.system-requirements-item.expanded .requirement { + opacity: 1; + height: auto; + transition: all 0.3s ease-in-out; +} + +.system-requirements-item.system-requirements-open .requirement { + display: block; +} + +.system-requirements-container .default-content-wrapper p a { + font: normal normal normal 12px/14px var(--body-font-family); + padding: 0 30px 0 0; + color: #006EFF; + border: 0; + display: inline-block; + position: relative; +} + +.system-requirements-container .default-content-wrapper p a::before { + content: url("/_src/icons/book-sharp-regular.svg"); + margin-right: 10px; + width: 14px; + height: 16px; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); + display: inline-block; + position: relative; + top: 3px; +} + +.system-requirements-container .default-content-wrapper p a:hover { + color: #006EFF; + text-decoration: underline; +} + +.system-requirements-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + margin: 0 auto; +} + +@media (min-width: 992px) { /* desktop */ + .system-requirements-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + .system-requirements-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .default-content-wrapper { + max-width: var(--section-desktop-max-width); + padding: 23px var(--section-desktop-padding); + border-radius: 0; + } +} + +@media (min-width: 1200px) { + .system-requirements-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .system-requirements-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/system-requirements/system-requirements.js b/_src/blocks/system-requirements/system-requirements.js new file mode 100644 index 000000000..48b7ad480 --- /dev/null +++ b/_src/blocks/system-requirements/system-requirements.js @@ -0,0 +1,72 @@ +function expandItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + const transitionEndCallback = () => { + content.removeEventListener('transitionend', transitionEndCallback); + content.style.height = 'auto'; + }; + content.addEventListener('transitionend', transitionEndCallback); + item.classList.add('expanded'); +} + +function collapseItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + requestAnimationFrame(() => { + item.classList.remove('expanded'); + content.style.height = 0; + }); +} + +function handleAccordionItemClick(item, items) { + if (!item.classList.contains('expanded')) { + items.filter((i) => i.classList.contains('expanded')).forEach((i) => collapseItem(i)); + expandItem(item); + } else { + collapseItem(item); + } +} + +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + // const blockParent = block.closest('.section'); + // blockParent.classList.add('we-container'); + } + + const items = Array.from(block.querySelectorAll(':scope > div')); + items.forEach((item) => { + item.classList.add('system-requirements-item'); + const [header, content] = item.children; + header.classList.add('system'); + + if (content) { + content.classList.add('requirement'); + // check if .accordion-item-content has a

      + // const p = content.querySelector('ul li p'); + // // if it doesn't, add a

      and move the content inside + // if (!p) { + // const newP = document.createElement('p'); + // newP.innerHTML = content.querySelector('ul li').innerHTML; + // content.querySelector('ul li').innerHTML = ''; + // content.querySelector('ul li').appendChild(newP); + // } + } + + if ([...block.classList].includes('action-only-on-header')) { + header.addEventListener('click', handleAccordionItemClick.bind(null, header.parentElement, items)); + } else { + item.addEventListener('click', handleAccordionItemClick.bind(null, item, items)); + } + }); + + if (block.classList.contains('first-open')) { + items[0].classList.add('expanded'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/tabs-component/tabs-component.css b/_src/blocks/tabs-component/tabs-component.css new file mode 100644 index 000000000..1363f7209 --- /dev/null +++ b/_src/blocks/tabs-component/tabs-component.css @@ -0,0 +1,248 @@ +.tabs-component-container .tabs-component { + display: flex; + flex-direction: column; + align-items: center; + margin-top: 48px; +} + +.tabs-component-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.tabs-component-container .icon svg { + width: 12px; + height: 14px; + padding-right: 2px; + fill: #fff; +} + +.tabs-component-container h3 { + font: normal normal bold 24px/28px Arial, sans-serif; +} + +.tabs-component-container p { + font: normal normal normal 16px/24px Arial, sans-serif; +} + +.tabs-component-container span { + font: normal normal bold 16px/18px Arial, sans-serif; +} + +.tabs-component-container .title-class div { + max-width: 630px; + text-align: center; + margin-bottom: 27px; + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.tabs-component-container .subtitle-class div { + max-width: 630px; + text-align: center; + margin-bottom: 67px; + font: normal normal normal 18px/26px Arial, sans-serif; +} + +.tabs-component-container .tabs-container { + display: flex; + justify-content: center; + margin-bottom: 40px; + flex-wrap: wrap; + border-bottom: 1px solid #E4F2FF; +} + +.tabs-component-container .card-container { + display: flex; + flex-direction: column-reverse; + align-items: center; + gap: 3%; +} + +.tabs-component-container .hide { + display: none; +} + +.tabs-component-container .tabs-container button { + background-color: white; + color: black; + border: 0; + font: normal normal bold 18px/21px Arial, sans-serif; + padding: 9px; + display: flex; + gap: 10px; + align-items: center; + position: relative; + cursor: pointer; +} + +.tabs-component-container a { + color: #006dff !important; + background-color: #fff !important; + border: 0 !important; +} + +.tabs-component-container a::after { + opacity: 1; + margin-left: 0; +} + +.tabs-component-container .tabs-container button a { + background-color: white; + border: 0; + font: normal normal bold 18px/21px Arial, sans-serif; + padding: 9px; + margin-bottom: 10px; + display: flex; + gap: 10px; + align-items: center; +} + +/* stylelint-disable-next-line no-descending-specificity */ +.tabs-component-container .card-container a { + overflow: visible; + padding-left: 0 !important; +} + +.tabs-component-container .card-container a .button-text { + transform: unset; +} + +.tabs-component-container .card-container a:hover { + color: #0A53C5; +} + +.tabs-component-container .card-container a::after { + content: '\2192'; + width: 24px; + height: 24px; + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + margin-left: 2px; + margin-bottom:2px; + mask: none !important; +} + +.tabs-component-container .card-container a:hover::after { + transform: translateX(5px); +} + +.tabs-component-container .tabs-container button::after { + background: #006eff; + border-radius: 0; + content: ""; + height: 4px; + position: absolute; + left: 0; + bottom: 0; + width: 0; + z-index: 1; +} + +.tabs-component-container .tabs-container button.selected::after { + transition: all 1s ease; + width: 100%; +} + +.tabs-component-container .left { + width: 80%; +} + +.tabs-component-container .left img { + border-radius: 20px; + width: auto; + max-width: 100%; + height: auto; +} + +.tabs-component-container .right { + width: 80%; + display: flex; + flex-direction: column; + justify-content: center; +} + +.tabs-component-container .right p { + font-size: 16px; +} + +.tabs-component-container .tabs-container button picture img { + width: 50px; + height: auto; +} + +.tabs-component-container button strong { + display: none; +} + +.tabs-component-container .tabs-container picture { + display: flex; + align-items: center; +} + +.tabs-component-container { + align-items: normal !important; +} + +@media (min-width: 768px) { + .tabs-component-container .tabs-container { + flex-wrap: nowrap; + } + + .tabs-component-container .left { + width: 60%; + } + + .tabs-component-container .right { + width: 60%; + } +} + +@media (min-width: 992px) { + .tabs-component-container .card-container { + flex-direction: row; + width: 830px; + } + + .tabs-component-container button strong { + display: block; + } + + .tabs-component-container .tabs-container button picture img { + width: 30px; + } + + .tabs-component-container .left { + width: 50%; + } + + .tabs-component-container .right { + width: 50%; + } + + .tabs-component-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .tabs-component-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .tabs-component-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/tabs-component/tabs-component.js b/_src/blocks/tabs-component/tabs-component.js new file mode 100644 index 000000000..b9ebc69f7 --- /dev/null +++ b/_src/blocks/tabs-component/tabs-component.js @@ -0,0 +1,83 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const parentSelector = block.closest('.section'); + // eslint-disable-next-line no-unused-vars + const metaData = parentSelector.dataset; + const [title, subtitle, tabsTitle, ...sections] = block.children; + + title.classList.add('title-class'); + subtitle.classList.add('subtitle-class'); + // Add class 'tabs-container' to the first div + tabsTitle.classList.add('tabs-container'); + + // Get the container for the buttons + const container = block.querySelector('.tabs-container'); + + // Check if the container exists + if (container) { + const divs = container.querySelectorAll('div'); + + // Loop through each div to create buttons + divs.forEach((div, index) => { + const button = document.createElement('button'); + if (index === 0) button.classList.add('selected'); + button.innerHTML = div.innerHTML; // Use innerHTML instead of textContent + button.addEventListener('click', () => { + // Remove 'selected' class from all buttons + const buttons = block.querySelectorAll('.tabs-container button'); + buttons.forEach((btn) => btn.classList.remove('selected')); + + // Add 'selected' class to the clicked button + button.classList.add('selected'); + + // Hide all card-container elements + const cardContainers = block.querySelectorAll('.card-container'); + cardContainers.forEach((card) => card.classList.add('hide')); + + // Show the corresponding card-container element based on the index + sections[index].classList.remove('hide'); + }); + + div.parentNode.replaceChild(button, div); + }); + } else { + // eslint-disable-next-line no-console + console.error('Container not found'); + } + + // click on the next element every 5 seconds + // setInterval(() => { + // const buttons = block.querySelectorAll('.tabs-container button'); + // const selectedButton = block.querySelector('.tabs-container button.selected'); + // const buttonIndex = Array.from(buttons).indexOf(selectedButton); + // const nextIndex = (buttonIndex + 1) % buttons.length; + // buttons[nextIndex].click(); + // }, 6000); + + // Add classes to each card-container and hide all but the first one + sections.forEach((element, index) => { + element.classList.add('card-container'); + if (index === 0) { + element.classList.add('show'); + } + if (index !== 0) { + element.classList.add('hide'); + } + + // Add classes to children divs + const photoDiv = element.querySelector('div:nth-child(1)'); + const textDiv = element.querySelector('div:nth-child(2)'); + photoDiv.classList.add('left'); + textDiv.classList.add('right'); + }); + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/solutions/blocks/tabs/tabs.css b/_src/blocks/tabs/tabs.css similarity index 100% rename from solutions/blocks/tabs/tabs.css rename to _src/blocks/tabs/tabs.css diff --git a/solutions/blocks/tabs/tabs.js b/_src/blocks/tabs/tabs.js similarity index 100% rename from solutions/blocks/tabs/tabs.js rename to _src/blocks/tabs/tabs.js diff --git a/_src/blocks/teaser-logos/teaser-logos.css b/_src/blocks/teaser-logos/teaser-logos.css new file mode 100644 index 000000000..a64d8f203 --- /dev/null +++ b/_src/blocks/teaser-logos/teaser-logos.css @@ -0,0 +1,89 @@ +/* stylelint-disable custom-property-pattern */ +.teaser-logos-container.section { + padding: 0; + background: #EFF6FF; +} + +.teaser-logos-container .main-wrapper { + display: flex; + height: 160px; +} + +.teaser-logos-container .default-content-wrapper { + display: flex; + padding-top: 0 !important; + height: 200px; +} + +.teaser-logos-container .main-wrapper .col, +.teaser-logos-container .default-content-wrapper .col { + display: flex; + justify-content: center; + position: relative; + width: 50%; +} + +.teaser-logos-container .main-wrapper .col { + background: #EFF6FF; +} + +.teaser-logos-container .main-wrapper .col:first-child::before { + content: ''; + display: block; + width: 0; + height: 0; + border-left: 50px solid transparent; + border-right: 50px solid transparent; + border-bottom: 170px solid var(--backgroundColor); + transform: rotate(180deg); + position: absolute; + right: -20px; + top: 0; + z-index: 2; +} + +.teaser-logos-container .main-wrapper .col:last-child::before { + content: ''; + display: block; + width: 0; + height: 0; + border-left: 50px solid transparent; + border-right: 50px solid transparent; + border-bottom: 170px solid var(--backgroundColor); + transform: rotate(0deg); + position: absolute; + left: -37.5px; + top: 0; + z-index: 1; +} + +.teaser-logos-container .default-content-wrapper .col .img-wrapper { + padding-top: 30px; + position: relative; + z-index: 3; + width: 100%; +} + +.teaser-logos-container .default-content-wrapper .col .img-wrapper img { + object-fit: cover; + width: 100%; +} + +@media screen and (min-width: 768px) { + .teaser-logos-container .main-wrapper { + height: 400px; + } + + .teaser-logos-container .main-wrapper .col:first-child::before, + .teaser-logos-container .main-wrapper .col:last-child::before { + border-bottom-width: 400px; + } + + .teaser-logos-container .default-content-wrapper .col .img-wrapper { + width: 50%; + height: 180px; + display: flex; + align-items: center; + } +} + diff --git a/_src/blocks/teaser-logos/teaser-logos.js b/_src/blocks/teaser-logos/teaser-logos.js new file mode 100644 index 000000000..3b78433f3 --- /dev/null +++ b/_src/blocks/teaser-logos/teaser-logos.js @@ -0,0 +1,11 @@ +export default async function decorate(block) { + const boxes = [...block.children[0].children]; + + block.innerHTML = ` +

      + ${boxes.map((box) => ` +
      ${box.innerHTML}
      + `).join('')} +
      + `; +} diff --git a/_src/blocks/terms/terms.css b/_src/blocks/terms/terms.css new file mode 100644 index 000000000..a12b4c276 --- /dev/null +++ b/_src/blocks/terms/terms.css @@ -0,0 +1,145 @@ +.terms-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1290px; + --section-desktop-padding: 20px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); + + background-color: #f2f2f2; +} + +@media (min-width: 992px) { /* desktop */ + .terms-wrapper { + max-width: var(--section-desktop-max-width); + padding: 15px var(--section-desktop-padding) 40px var(--section-desktop-padding); + margin: 0 auto; + } +} + +.terms-container h5 { + font-size: 16px; + font-weight: bold; + margin: 0; +} + +.terms-container h6 { + font-size: 16px; + font-weight: bold; + margin: 0; +} + +.terms-container .terms div, +.terms-container .terms div p { + font-size: 12px; +} + +.terms-container .terms div p strong { + font-weight: bold; + margin-top: 15px; +} + +.terms-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + margin: 0 auto; +} + +.terms.border-on-top { + border-top: 1px solid #dedede; + padding-top: 20px; +} + +@media (max-width: 992px) { /* mobile/tablet */ + .terms-wrapper { + padding: var(--body-padding); + } + + .terms-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .default-content-wrapper { + max-width: var(--section-desktop-max-width); + padding: 23px var(--section-desktop-padding); + border-radius: 0; + } +} + +@media (min-width: 1200px) { + .terms-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .terms-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/terms/terms.js b/_src/blocks/terms/terms.js new file mode 100644 index 000000000..fe60b0391 --- /dev/null +++ b/_src/blocks/terms/terms.js @@ -0,0 +1,15 @@ +export default async function decorate(block, options) { + block.closest('.section').id = 'tos'; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.terms-wrapper'); + blockParent.classList.add('we-container'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/testimonials-component/testimonials-component.css b/_src/blocks/testimonials-component/testimonials-component.css new file mode 100644 index 000000000..8f18b135c --- /dev/null +++ b/_src/blocks/testimonials-component/testimonials-component.css @@ -0,0 +1,172 @@ +.testimonials-component-container { + display: flex; + flex-direction: column; + align-items: center; + font: italic normal normal 14px/19px Arial, sans-serif; +} + +.testimonials-component-container h2 { + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.testimonials-component-container .testimonials-component { + display: flex; + flex-direction: column; + align-items: center; + gap: 3%; +} + +.testimonials-component-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin: 15px auto; +} + +.testimonials-component-container .title-class { + text-align: center; + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.testimonials-component-container .subtitle-class { + font: normal normal normal 18px/21px Arial, sans-serif; + margin-bottom: 40px; + text-align: center; + max-width: 90%; +} + +.testimonials-component-container .review-container { + display: flex; + align-items: flex-start; + flex: 1; + gap: 2%; + background: #edf9ff; + padding: 26px 23px; + border-radius: 16px; +} + +.testimonials-component-container.grey-bck .review-container { + background-color: #F6F6F6;; +} + +.testimonials-component-container hr { + margin-left: 0; + width: 24px; + margin-bottom: 8px; + border: 1px solid #00439c; +} + +.testimonials-component-container .review { + width: 90%; +} + +.testimonials-component-container .review p { + width: 90%; + margin-top: 0; +} + +.testimonials-component-container .review p:last-child { + font-style: normal; +} + +.testimonials-component-container.grey-bck .review p { + font-size: 14px; + font-style: normal; +} + +.testimonials-component-container .hide { + display: none; +} + +.testimonials-component-container .show { + display: flex; +} + +.testimonials-component-container .navigation-container { + display: flex; + justify-content: space-between; + gap: 3%; + max-width: 90%; + width: 100%; + margin-top: 20px; + align-items: center; +} + +.testimonials-component-container .buttons-container { + display: flex; + gap: 3%; +} + +.testimonials-component-container .next-button, +.testimonials-component-container .prev-button { + width: 45px; + height: 45px; + border: 0; + background-color: #edf9ff; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; +} + +.testimonials-component-container .prev-button { + margin-right: 10px; +} + +.testimonials-component-container .next-button:hover, +.prev-button:hover { + border: 1px solid #006eff; +} + +@media (min-width: 768px) { + .testimonials-component-container .title-class { + width: 715px; + } + + .testimonials-component-container .reviews-container { + display: flex; + flex-direction: column; + } +} + +@media (min-width: 990px) { + .testimonials-component-container .reviews-container { + display: flex; + flex-direction: row; + gap: 3%; + } + + .testimonials-component-container .hide { + display: flex; + } + + .testimonials-component-container .show { + display: flex; + } + + .testimonials-component-container .buttons-container { + display: none; + } + + .testimonials-component-container .navigation-container { + justify-content: center; + } + + .testimonials-component-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .testimonials-component-container .testimonials-component { + max-width: 1294px; + } + + .testimonials-component-container.we-container { + max-width: 1290px; + padding-left: 20px; + padding-right: 20px; + } +} \ No newline at end of file diff --git a/_src/blocks/testimonials-component/testimonials-component.js b/_src/blocks/testimonials-component/testimonials-component.js new file mode 100644 index 000000000..beaabf0b5 --- /dev/null +++ b/_src/blocks/testimonials-component/testimonials-component.js @@ -0,0 +1,110 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const parentSelector = block.closest('.section'); + // eslint-disable-next-line no-unused-vars + const metaData = parentSelector.dataset; + const [title, subtitle, source, ...reviews] = block.children; + + title.classList.add('title-class'); + subtitle.classList.add('subtitle-class'); + source.classList.add('source-class'); + + // Create a new div for reviews + const reviewsContainer = document.createElement('div'); + reviewsContainer.classList.add('reviews-container'); + + // Iterate over each review element + reviews.forEach((review, index) => { + review.classList.add('review'); + + // Create SVG element + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); + svg.setAttribute('viewBox', '0 0 448 512'); + svg.setAttribute('width', '32px'); // Set width to 32 pixels + svg.setAttribute('height', '32px'); // Set height to 32 pixels + svg.style.fill = '#006EFF'; // Set the SVG color to blue + svg.innerHTML = ''; + + // Create a container for the SVG and review content + const reviewContainer = document.createElement('div'); + reviewContainer.classList.add('review-container'); + if (index === 0) { + reviewContainer.classList.add('show'); + } else { + reviewContainer.classList.add('hide'); + } + + // Append SVG and review to the review container + reviewContainer.appendChild(svg); + reviewContainer.appendChild(review); + + // Append review container to the reviews container + reviewsContainer.appendChild(reviewContainer); + }); + + // Append the reviews container to the block + block.appendChild(reviewsContainer); + + // Create navigation buttons for the slider + const prevButton = document.createElement('button'); + // Set SVG icon for previous button with color #006EFF + prevButton.innerHTML = ''; + prevButton.classList.add('prev-button'); + prevButton.addEventListener('click', () => { + // eslint-disable-next-line no-use-before-define + navigateSlider(-1); + }); + + const nextButton = document.createElement('button'); + // Set SVG icon for next button with color #006EFF + nextButton.innerHTML = ` + +`; + nextButton.classList.add('next-button'); + nextButton.addEventListener('click', () => { + // eslint-disable-next-line no-use-before-define + navigateSlider(1); + }); + + // Create navigation container + const navigationContainer = document.createElement('div'); + navigationContainer.classList.add('navigation-container'); + block.appendChild(navigationContainer); + navigationContainer.appendChild(source); + // create buttons container + const buttonsContainer = document.createElement('div'); + buttonsContainer.classList.add('buttons-container'); + navigationContainer.appendChild(buttonsContainer); + // Append navigation buttons to the block + buttonsContainer.appendChild(prevButton); + buttonsContainer.appendChild(nextButton); + + // Slider navigation function + let currentIndex = 0; + const reviewsCount = reviews.length; + + function navigateSlider(direction) { + const currentReview = block.querySelector('.show'); + const nextIndex = (currentIndex + direction + reviewsCount) % reviewsCount; + const nextReview = reviewsContainer.children[nextIndex]; + + currentReview.classList.remove('show'); + currentReview.classList.add('hide'); + + nextReview.classList.remove('hide'); + nextReview.classList.add('show'); + + currentIndex = nextIndex; + } + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/thank-you/thank-you.css b/_src/blocks/thank-you/thank-you.css new file mode 100644 index 000000000..e5fa9623e --- /dev/null +++ b/_src/blocks/thank-you/thank-you.css @@ -0,0 +1,244 @@ +.thank-you-container { + .thank-you { + display: flex; + flex-direction: column; + flex: 0 1 50%; + font-family: Arial, Roboto, sans-serif; + + @media (min-width: 768px) { + & { + flex-direction: row; + } + } + + img { + max-width: 100%; + width: auto; + height: auto; + } + + .content-right { + padding-left: 20px; + display: flex; + align-items: end; + justify-content: center; + flex: 1 0 auto; + + + img { + max-width: 520px; + box-shadow: 0 35px 40px 0 #0000000F; + } + } + + .content-left { + max-width: 630px; + + >p:first-of-type { + color: #3782F9; + font-size: 18px; + line-height: clamp(15px, 5vw, 44px); + } + + h1 { + font-size: clamp(24px, 5vw, 53px); + font-weight: 400; + line-height: clamp(30px, 5vw, 77px); + + strong { + color: #006EFF; + font-weight: normal; + } + } + + .qr-content { + display: flex; + font-size: clamp(16px, 5vw, 20px); + align-items: center; + + img { + max-width: 170px; + height: auto; + box-shadow: 0 35px 40px 0 #0000000F; + } + } + } + + /* Importing from styles.css to be able to import in aem */ + p a { + font-family: var(--body-font-family); + font-size: var(--body-font-size-s); + font-style: normal; + font-weight: var(--font-weight-bold); + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: var(--button-link-color); + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + } + + p a::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('https::/bitdefender.com/_src/icons/arrow-right.svg'); + mask: url('https::/bitdefender.com/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + opacity: 0; + margin-left: -10px; + } + + p a:hover, p a:focus { + background-color: var(--button-hover-background-color); + border: 2px solid var(--button-hover-background-color); + cursor: pointer; + } + + p a:hover::after { + transform: translateX(5px); + opacity: 1; + } + } + + &.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; + + + @media (min-width: 990px) { + & { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + } + + @media (min-width: 1200px) { + & { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } + } + + @media (min-width: 1600px) { + & { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } + } + } + + @media (min-width: 990px) { + margin-top: 120px; + margin-bottom: 120px; + } + + +} + +/* stylelint-disable-next-line no-duplicate-selectors */ +.thank-you-container { + /* colors */ + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + + /* fonts */ + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + + /* font weights */ + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + + /* body sizes */ + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + + /* heading sizes */ + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + + /* nav height */ + --nav-height: 63px; + --nav-height-desktop: 40px; + + /* body width */ + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1300px; + --section-desktop-padding: 20px; + --section-large-desktop-max-width: 1332px; + --section-large-desktop-padding: 50px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + + /* cta styles */ + --cta-background-light-blue: var(--background-light-blue) +} \ No newline at end of file diff --git a/_src/blocks/thank-you/thank-you.js b/_src/blocks/thank-you/thank-you.js new file mode 100644 index 000000000..fcb4a11f4 --- /dev/null +++ b/_src/blocks/thank-you/thank-you.js @@ -0,0 +1,43 @@ +// Function to dispatch 'shadowDomLoaded' event +function dispatchShadowDomLoadedEvent() { + const event = new CustomEvent('shadowDomLoaded', { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + window.dispatchEvent(event); +} + +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } else { + // eslint-disable-next-line no-param-reassign + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const [richTextPicture, richTextQR] = block.children; + const [richTextPictureText, richTextPicturePicture] = richTextPicture.children; + const [richTextQRText, richTextQRPicture] = richTextQR.children; + const html = ` +
      + ${richTextPictureText.innerHTML} +
      + ${richTextQRText.innerHTML} +
      + ${richTextQRPicture.innerHTML} +
      +
      +
      +
      + ${richTextPicturePicture.innerHTML} +
      + `; + + block.innerHTML = html; + + dispatchShadowDomLoadedEvent(); +} diff --git a/_src/blocks/trusted-hero/trusted-hero.css b/_src/blocks/trusted-hero/trusted-hero.css new file mode 100644 index 000000000..429f7098a --- /dev/null +++ b/_src/blocks/trusted-hero/trusted-hero.css @@ -0,0 +1,166 @@ +.trusted-hero-container.section { + padding: 0; + background: #EFF6FF; + color: black; +} + +.trusted-hero-container .trusted-hero-wrapper .block { + display: flex; + flex-direction: column; +} + +.trusted-hero-container h1, +.trusted-hero-container h2 { + font: normal normal normal 28px/32px var(--font-ibm); +} + +.trusted-hero-container h1 { + font-weight: 500; +} + +.trusted-hero-container .video-wrapper { + height: 200px; + position: relative; +} + +.trusted-hero-container .video-wrapper iframe { + width: 100%; + height: 100%; + object-fit: cover; + position: absolute; + left: 0; +} + +.trusted-hero-container .default-content-wrapper { + position: relative; + padding-top: 20px !important; + z-index: 4; + order: -1; + padding-bottom: 140px; +} + +.trusted-hero-container p.button-container:nth-last-child(1) { + position: absolute; + bottom: 0; + left: 1em; + right: 1em; +} + +.trusted-hero-container p.button-container:nth-last-child(2) { + position: absolute; + bottom: 60px; + left: 1em; + right: 1em; +} + +.trusted-hero-container p.button-container a { + background-color: transparent !important; + border: solid black 1px !important; + color: black; + width: 100%; + justify-content: center; + font-weight: 500 !important; +} + +.trusted-hero-container p.button-container:nth-last-child(2) a { + width: 100%; + justify-content: center; + font-weight: 400; + border: 1px solid var(--blue); +} + +.trusted-hero-container p.button-container a:hover { + background-color: var(--blue) !important; + border: 1px solid var(--blue) !important; + color: white; +} + +@media (min-width: 768px) { + /* .trusted-hero-container a.button:any-link:not(.modal, .primary) { */ + + /* width: unset; */ + + /* justify-content: unset; */ + + /* display: inline-flex; */ + + /* margin-right: 15px; */ + + /* } */ + .trusted-hero-container h1, + .trusted-hero-container h2 { + font: normal normal 500 29px / 33px var(--font-ibm); + } + + .trusted-hero-container h2 { + margin: 50px 0 0; + color: black; + } +} + +@media (min-width: 992px) { + .trusted-hero-container { + background: #EFF6FF; + color: black; + height: 670px; + } + + .trusted-hero-container h1 { + font: normal normal 500 47px / 48px var(--font-ibm); + } + + .trusted-hero-container .trusted-hero-wrapper { + height: 100%; + } + + .trusted-hero-container .trusted-hero-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .trusted-hero-container .rte-wrapper { + width: 100%; + } + + .trusted-hero-container .video-wrapper { + width: 100%; + height: 100%; + } + + .trusted-hero-container .default-content-wrapper { + padding-top: 0 !important; + order: unset; + position: absolute; + left: 0; + right: 0; + height: 100%; + display: flex; + align-items: center; + gap: 30px; + padding-bottom: unset; + } + + .trusted-hero-container .default-content-wrapper > .rte-wrapper { + width: 555px; + padding-right: 4em; + } + + .trusted-hero-container .default-content-wrapper > .video-wrapper { + width: 60%; + height: 385px; + } + + .trusted-hero-container .default-content-wrapper p.button-container { + position: unset; + display: inline-block; + } + + .trusted-hero-container a.button:any-link:not(.modal, .primary) { + width: unset; + justify-content: unset; + display: inline-flex; + margin-right: 15px; + } +} + diff --git a/_src/blocks/trusted-hero/trusted-hero.js b/_src/blocks/trusted-hero/trusted-hero.js new file mode 100644 index 000000000..18231b6ee --- /dev/null +++ b/_src/blocks/trusted-hero/trusted-hero.js @@ -0,0 +1,34 @@ +export default async function decorate(block) { + const [rte, videoUrl] = [...block.children]; + + const autoplay = false; + const url = new URL(videoUrl.textContent.trim()); + const usp = new URLSearchParams(url.search); + const suffix = autoplay ? '&muted=1&autoplay=1' : ''; + let vid = usp.get('v') ? encodeURIComponent(usp.get('v')) : ''; + const embed = url.pathname; + + if (url.origin.includes('youtu.be')) { + [, vid] = url.pathname.split('/'); + } + + block.innerHTML = ` +
      +
      ${rte.innerHTML}
      +
      + +
      +
      + `; + + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); +} diff --git a/_src/blocks/trusted-main-carousel/trusted-main-carousel.css b/_src/blocks/trusted-main-carousel/trusted-main-carousel.css new file mode 100644 index 000000000..cbeff5e19 --- /dev/null +++ b/_src/blocks/trusted-main-carousel/trusted-main-carousel.css @@ -0,0 +1,183 @@ +.trusted-main-carousel-container { + background: white; +} + +.trusted-main-carousel-container .navigation-wrapper { + display: flex; + scrollbar-width: none; + overflow: auto; +} + +.trusted-main-carousel-container .navigation-wrapper::-webkit-scrollbar { + display: none; /* For Chrome, Safari, Opera */ +} + +.trusted-main-carousel-container .navigation-wrapper .first-nav { + display: flex; + cursor: pointer; + border-radius: 8px; + background: #EFF6FF; +} + +.trusted-main-carousel-container .navigation-wrapper .second-nav { + display: none; +} + +.trusted-main-carousel-container .navigation-wrapper .nav-item { + color: black; + font-weight: 500; + font-size: 9px; + flex-shrink: 0; + padding: 15px; +} + +.trusted-main-carousel-container .default-content-wrapper { + overflow: hidden; +} + +.trusted-main-carousel-container .navigation-wrapper .nav-item.active { + background: #006EFF; + border-radius: 8px; + color: white; + transition: all .25s linear; + position: relative; + z-index: 1; +} + +.trusted-main-carousel-container .content-wrapper { + color: black; + display: flex; + transform: translateX(0); + transition: transform 0.25s ease-out; +} + +.trusted-main-carousel-container .block.scrolling .content-wrapper { + overflow: unset; +} + +.trusted-main-carousel-container .content-wrapper .slide { + width: 100%; + flex-shrink: 0; + box-sizing: border-box; + margin-right: 50px; +} + +.trusted-main-carousel-container .content-wrapper .slide u { + display: none; +} + +.trusted-main-carousel-container .content-wrapper .slide>* { + position: relative; +} + +.trusted-main-carousel-container .content-wrapper .slide>:first-child p.button-container { + display: flex; + justify-content: center; +} + +.trusted-main-carousel-container .content-wrapper .slide>:last-child { + width: calc(100% + 2em); + margin-left: -1em; + height: 200px; + top: -15px; + z-index: -1; +} + +.trusted-main-carousel-container .content-wrapper .slide>:last-child img { + object-fit: cover; + width: 100%; + height: 100%; +} + +.trusted-main-carousel-container .content-wrapper .slide>:first-child p.button-container a.button:any-link { + background-color: white; + color: black; + font-weight: normal; + border: 1px solid black; + width: 250px; + justify-content: center; +} + +.trusted-main-carousel-container .content-wrapper .slide>:first-child img { + width: 160px; +} + +@media (min-width: 768px) { + .trusted-main-carousel-container .navigation-wrapper .nav-item { + font-size: 100%; + } + + .trusted-main-carousel-container .navigation-wrapper .second-nav { + display: flex; + margin-left: auto; + } + + .trusted-main-carousel-container .left-arrow, + .trusted-main-carousel-container .right-arrow { + color: black; + } + + .trusted-main-carousel-container .left-arrow svg { + transform: rotate(180deg); + } + + .trusted-main-carousel-container .arrow { + width: 100px; + } + + .trusted-main-carousel-container .arrow svg { + width: 100%; + height: 50px; + } + + .trusted-main-carousel-container .arrow svg path { + fill: black; + } + + .trusted-main-carousel-container .left-arrow { + margin-left: auto; + } + + .trusted-main-carousel-container .content-wrapper .slide>:first-child p.button-container { + position: unset; + } + + .trusted-main-carousel-container .content-wrapper .slide>:last-child { + height: 400px; + } +} + +@media (min-width: 992px) { + .trusted-main-carousel-container .content-wrapper .slide { + display: flex; + gap: 50px; + margin-top: 30px; + } + + .trusted-main-carousel-container .navigation-wrapper .nav-item { + padding: 15px 30px; + } + + .trusted-main-carousel-container .content-wrapper .slide>:last-child { + width: calc(60% - 50px); + margin-left: unset; + height: auto; + } + + .trusted-main-carousel-container .content-wrapper .slide>:first-child p.button-container { + justify-content: unset; + } + + .trusted-main-carousel-container .content-wrapper .slide>:first-child>*:not(h2) { + margin: 40px 0; + } + + .trusted-main-carousel-container .content-wrapper .slide>:last-child img { + object-fit: contain; + } + + .trusted-main-carousel-container .content-wrapper .slide>div { + width: calc(40% - 50px); + flex-shrink: 0; + } +} \ No newline at end of file diff --git a/_src/blocks/trusted-main-carousel/trusted-main-carousel.js b/_src/blocks/trusted-main-carousel/trusted-main-carousel.js new file mode 100644 index 000000000..c5138b1b4 --- /dev/null +++ b/_src/blocks/trusted-main-carousel/trusted-main-carousel.js @@ -0,0 +1,167 @@ +import { debounce, isView } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const slides = [...block.children]; + const AUTOMATIC_SLIDING = { + enabled: true, + viewport: 'desktop', + slideDelay: 3 * 1000, + }; + + const state = { + currentStep: 0, + carouselIsFocused: false, + currentInterval: null, + }; + + const navItemsNames = slides.map((slideEl) => slideEl.children[0].firstElementChild.textContent); + + block.classList.add('default-content-wrapper'); + block.innerHTML = ` + + +
      + ${slides.map((slide, index) => ` +
      + ${slide.innerHTML} +
      + `).join('')} +
      + `; + + const contentWrapper = block.querySelector('.content-wrapper'); + + const navItems = block.querySelectorAll('.nav-item'); + const slideItems = block.querySelectorAll('.slide'); + const leftArrow = block.querySelector('.left-arrow'); + const rightArrow = block.querySelector('.right-arrow'); + function selectNavItem(itemPosition) { + navItems.forEach((item) => item.classList.remove('active')); + navItems[itemPosition].classList.add('active'); + } + + function selectSlideItem(itemPosition) { + slideItems.forEach((item) => item.classList.remove('active')); + slideItems[itemPosition].classList.add('active'); + } + + function slideToSection(itemPosition) { + block.classList.add('scrolling'); + + const transformValue = -100 * (itemPosition); + const offset = 50 * itemPosition; + contentWrapper.style.transform = `translateX(calc(${transformValue}% - ${offset}px ))`; + setTimeout(() => { + block.classList.remove('scrolling'); + }, 200); + } + + function selectStep(itemPosition) { + state.currentStep = itemPosition; + selectNavItem(itemPosition); + selectSlideItem(itemPosition); + slideToSection(itemPosition); + } + + function endAutomaticSliding(interval) { + clearInterval(interval || state.currentInterval); + } + + function beginAutomaticSliding() { + if (!AUTOMATIC_SLIDING.enabled) return; + + endAutomaticSliding(); + + if (state.carouselIsFocused || !isView(AUTOMATIC_SLIDING.viewport)) { + return; + } + + const interval = setInterval(() => { + const isLastStep = state.currentStep === navItems.length - 1; + const nextStepToSelect = isLastStep ? 0 : (state.currentStep + 1); + selectStep(nextStepToSelect); + + if (!isView(AUTOMATIC_SLIDING.viewport) || state.carouselIsFocused) { + endAutomaticSliding(interval); + } + }, AUTOMATIC_SLIDING.slideDelay); + + state.currentInterval = interval; + } + + function addEventListeners() { + block.addEventListener('mouseenter', () => { + state.carouselIsFocused = true; + endAutomaticSliding(); + }); + + block.addEventListener('mouseleave', () => { + state.carouselIsFocused = false; + beginAutomaticSliding(); + }); + + navItems.forEach((navEl, itemPosition) => { + navEl.addEventListener('click', () => { + selectStep(itemPosition); + }); + }); + + leftArrow.addEventListener('click', (e) => { + e.preventDefault(); + + const isFirstStep = state.currentStep === 0; + if (isFirstStep) { + return; + } + + selectStep(state.currentStep - 1); + }); + + rightArrow.addEventListener('click', (e) => { + e.preventDefault(); + + const isLastStep = state.currentStep === navItems.length - 1; + if (isLastStep) { + return; + } + + selectStep(state.currentStep + 1); + }); + } + + addEventListeners(); + + beginAutomaticSliding(); + window.addEventListener('resize', debounce(beginAutomaticSliding, 250)); +} diff --git a/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.css b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.css new file mode 100644 index 000000000..5a6c0876c --- /dev/null +++ b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.css @@ -0,0 +1,112 @@ +.trusted-teaser-impact-container { + background: white; + padding-top: 0 !important; +} + +.trusted-teaser-impact-container .carousel-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 30px; +} + +.trusted-teaser-impact .carousel-header .title { + color: black; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +.trusted-teaser-impact .carousel-header .title >:first-child { + margin: 0; +} + +.trusted-teaser-impact .box-wrapper { + display: flex; + flex-wrap: wrap; + gap: 20px; +} + +.trusted-teaser-impact .box-wrapper .box-item { + width: calc(50% - 10px); + flex-shrink: 0; + color: black; + position: relative; + padding-right: 10px; +} + +.trusted-teaser-impact .box-wrapper .box-item::after { + content: ''; + display: block; + width: 1px; + height: 80%; + position: absolute; + top: 10%; + right: -3px; + background: #006EFF; + opacity: 0.25; + visibility: hidden; +} + +.trusted-teaser-impact .box-wrapper .box-item:nth-child(1)::after, +.trusted-teaser-impact .box-wrapper .box-item:nth-child(3)::after { + visibility: visible; +} + +.trusted-teaser-impact .box-wrapper .box-item .icon { + width: 35px; + height: 35px; + margin: 0; +} + +.trusted-teaser-impact .box-wrapper .box-item .icon .cls-1 { + fill: #006EFF; +} + +.trusted-teaser-impact .box-wrapper .box-item .title { + font-size: 35px; + font-weight: bold; +} + +@media (min-width: 768px) { + .trusted-teaser-impact .box-wrapper .box-item .icon { + width: 50px; + height: 50px; + } + + .trusted-teaser-impact .box-wrapper .box-item:nth-child(2), + .trusted-teaser-impact .box-wrapper .box-item:nth-child(4) { + padding-left: 20px; + } + +} + +@media (min-width: 992px) { + .trusted-teaser-impact .box-wrapper .box-item { + width: calc(25% - 15px); + } + + .trusted-teaser-impact .box-wrapper .box-item .title { + font-size: 50px; + color: #35383C; + } + + .trusted-teaser-impact .box-wrapper .box-item .subtitle { + margin-top: 0; + } + + .trusted-teaser-impact .box-wrapper .box-item .icon { + width: 70px; + height: 70px; + } + + .trusted-teaser-impact .box-wrapper .box-item:nth-child(3) { + padding-left: 20px; + } + + .trusted-teaser-impact .box-wrapper .box-item:nth-child(2)::after { + visibility: visible; + } +} + diff --git a/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.js b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.js new file mode 100644 index 000000000..24ecf121c --- /dev/null +++ b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.js @@ -0,0 +1,38 @@ +import { decorateIcons } from '../../scripts/lib-franklin.js'; +import { debounce } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [titleEl, ...boxes] = [...block.children]; + + function render() { + block.classList.add('default-content-wrapper'); + + block.innerHTML = ` + + +
      + ${boxes.map((box) => ` +
      + ${box.children[0].children[0].innerHTML} + +
      + ${box.children[0].children[1].textContent} +
      + +

      + ${box.children[0].children[2].innerHTML} +

      +
      + `).join('')} +
      + `; + + decorateIcons(block); + } + + render(); + + window.addEventListener('resize', debounce(render, 250)); +} diff --git a/_src/blocks/video-carousel/video-carousel.css b/_src/blocks/video-carousel/video-carousel.css new file mode 100644 index 000000000..5d2fe43eb --- /dev/null +++ b/_src/blocks/video-carousel/video-carousel.css @@ -0,0 +1,269 @@ +.video-carousel-container{ + background-color: #F4F4F4; +} + +.video-carousel { + .carousel-container { + padding-left: 20px; + padding-right: 0; + display: flex; + justify-content: right; + overflow: hidden; + position: relative; + width: 100%; + margin: 0 auto; + } + + .carousel-track { + display: grid; + grid-auto-flow: column; + justify-content: left; + transition: transform 0.5s ease; + min-height: 100%; + width: 100%; + height: 100%; + overflow: visible; + } + + .carousel-item { + padding: 20px; + padding-right: 40px; + text-align: center; + } + + .carousel-item iframe { + border-radius: 20px; + width: 250px; + height: 150px; + } + + .video-thumbnail { + width: 100%; + border-radius: 10px; + cursor: pointer; + position: relative; + } + + .video-thumbnail img { + width: 100%; + border-radius: 10px; + } + + .video-thumbnail .play-button { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 50px; + color: white; + opacity: 0.8; + } + + .video-title { + font-size: 16px; + font-weight: 400; + margin-top: 10px; + color: #333; + } + + .carousel-navigation { + display: flex; + justify-content: center; + margin-top: 50px; + } + + .carousel-dot { + width: 23px; + height: 23px; + border-radius: 50%; + background-color: #ccc; + margin: 0 5px; + cursor: pointer; + transition: background-color 0.3s; + } + + .carousel-dot.active { + background-color: #006EFF; + } + + @media (min-width: 767px) { + .carousel-item{ + text-align: left; + padding-right: 50px; + } + + .carousel-container{ + padding-left: 2%; + } + + .carousel-dot:last-of-type{ + display: none; + } + + .carousel-item iframe { + min-width: 300px; + height: 220px; + border-radius: 40px; + } + + .video-title{ + font-size: 23px; + } + } + + @media (min-width:1020px){ + .carousel-container{ + padding-left: 3%; + } + + .carousel-item iframe{ + min-width: 400px; + min-height: 280px; + } + } + + @media (min-width:1200px) { + .carousel-container{ + padding-left: 8%; + } + + .carousel-item iframe { + min-width: 600px; + height: 360px; + } + } + + @media (min-width: 1750px) { + .carousel-container{ + padding-left: 13%; + } + } +} + +.video-carousel.no-carousel{ + .carousel-container{ + padding:20px; + justify-content: center; + } + + .carousel-track{ + justify-self: center ; + justify-content: space-around; + grid-auto-flow: row; + gap: 10px; + } + + .carousel-item{ + padding: 0; + padding-bottom: 10px; + text-align: center; + justify-items: center; + } + + .carousel-navigation{ + display: none; + } + + + .carousel-item iframe { + min-width: auto; + height: auto; + } + + @media (min-width:767px){ + .carousel-track{ + display: flex; + justify-content: center; + flex-wrap: wrap; + gap:50px; + } + + .carousel-container{ + padding:4%; + } + + .carousel-item{ + text-align: left; + width: 300px; + font-size: 16px; + } + + .video-carousel-container .carousel-item:nth-child(3) { + justify-self: center; + } + + .carousel-item iframe{ + min-width: 300px; + max-width: 100%; + min-height: 200px; + } + } + + @media (min-width:1020px){ + .carousel-track{ + display: grid; + grid-template-columns: repeat(3, 1fr); + } + + .carousel-container{ + padding:5%; + } + + .carousel-item{ + width: 280px; + font-size: 18px; + } + + .carousel-item iframe{ + min-width: 280px; + min-height: 200px; + } + } + + @media (min-width: 1200px){ + .carousel-container{ + padding:5% 10%; + } + + .carousel-item{ + width: 320px; + font-size: 23px; + } + + .carousel-item iframe{ + min-width: 320px; + min-height: 240px; + } + } + + @media (min-width: 1400px){ + .carousel-container{ + padding:5% 10%; + } + + .carousel-item{ + width: 380px; + } + + .carousel-item iframe{ + min-width: 380px; + min-height: 280px; + } + } + + @media (min-width: 1750px){ + .carousel-container{ + padding-left: 15%; + } + + .carousel-item{ + width: 440px; + font-size: 23px; + } + + .carousel-item iframe{ + min-width: 440px; + min-height: 300px; + } + } +} \ No newline at end of file diff --git a/_src/blocks/video-carousel/video-carousel.js b/_src/blocks/video-carousel/video-carousel.js new file mode 100644 index 000000000..64f58b952 --- /dev/null +++ b/_src/blocks/video-carousel/video-carousel.js @@ -0,0 +1,69 @@ +function createCarousel(block, videos, titles) { + const carouselContainer = document.createElement('div'); + carouselContainer.classList.add('carousel-container'); + + const carouselTrack = document.createElement('div'); + carouselTrack.classList.add('carousel-track'); + + videos.forEach((video, index) => { + const carouselItem = document.createElement('div'); + carouselItem.classList.add('carousel-item'); + + // Create an iframe element for embedding YouTube video + const iframeElement = document.createElement('iframe'); + iframeElement.setAttribute('src', `${video}`); + iframeElement.setAttribute('frameborder', '0'); + iframeElement.setAttribute('allow', 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'); + iframeElement.setAttribute('allowfullscreen', ''); + + const videoTitle = document.createElement('div'); + videoTitle.classList.add('video-title'); + videoTitle.textContent = titles[index]; + + carouselItem.appendChild(iframeElement); + carouselItem.appendChild(videoTitle); + carouselTrack.appendChild(carouselItem); + carouselTrack.scroll({ + behavior: 'smooth', + }); + }); + + carouselContainer.appendChild(carouselTrack); + block.appendChild(carouselContainer); + + // Carousel navigation logic + const carouselNav = document.createElement('div'); + carouselNav.classList.add('carousel-navigation'); + + videos.forEach((_, index) => { + const dot = document.createElement('div'); + dot.classList.add('carousel-dot'); + if (index === 0) dot.classList.add('active'); + // eslint-disable-next-line no-use-before-define + dot.addEventListener('click', () => moveToSlide(index)); + carouselNav.appendChild(dot); + }); + + block.appendChild(carouselNav); + + let currentIndex = 0; + function moveToSlide(index) { + const dots = document.querySelectorAll('.carousel-dot'); + dots[currentIndex].classList.remove('active'); + dots[index].classList.add('active'); + + currentIndex = index; + // eslint-disable-next-line no-unsafe-optional-chaining + carouselTrack.style.transform = `translateX(-${block.querySelector('.carousel-item')?.offsetWidth * index}px)`; + } +} + +export default function decorate(block) { + const videos = Object.values(block.closest('.section').dataset).filter((value) => value.includes('https://www.youtube.com/embed/')); + const titles = Object.keys(block.closest('.section').dataset) + .filter((key) => key.includes('title')) + .map((key) => block.closest('.section').dataset[key]); + if (videos) { + createCarousel(block, videos, titles); + } +} diff --git a/_src/blocks/video/video.css b/_src/blocks/video/video.css new file mode 100644 index 000000000..bcac2bf4d --- /dev/null +++ b/_src/blocks/video/video.css @@ -0,0 +1,87 @@ +.video { + width: unset; + text-align: center; + margin-top: 32px; + margin-bottom: 32px; +} + +.video.lazy-loading { + /* reserve an approximate space to avoid extensive layout shifts */ + aspect-ratio: 16/9; +} + +.video > div { + display: flex; + justify-content: center; + border-radius: 13px; + overflow: hidden; +} + +.video.left { + margin-right: auto; +} + +.video.center { + margin-left: auto; + margin-right: auto; +} + +.video.right { + margin-left: auto; +} + +.video video { + max-width: 100%; +} + +.video video[data-loading] { + /* reserve an approximate space to avoid extensive layout shifts */ + width: 100%; + aspect-ratio: 16/9; +} + +.video .video-placeholder { + width: 100%; + aspect-ratio: 16/9; + position: relative; +} + +.video .video-placeholder > * { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + inset: 0; +} + +.video .video-placeholder picture img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.video .video-placeholder-play button { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(3); + width: 22px; + height: 22px; + border: 2px solid; + border-radius: 20px; + padding: 0; +} + +.video .video-placeholder-play button::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 0; + height: 10px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 6px solid; + top: 4px; + left: 7px; +} \ No newline at end of file diff --git a/_src/blocks/video/video.js b/_src/blocks/video/video.js new file mode 100644 index 000000000..482179405 --- /dev/null +++ b/_src/blocks/video/video.js @@ -0,0 +1,108 @@ +/* + * Video Block + * Show a video referenced by a link + * https://www.hlx.live/developer/block-collection/video + */ +function embedYoutube(url, autoplay) { + const usp = new URLSearchParams(url.search); + const suffix = autoplay ? '&muted=1&autoplay=1' : ''; + let vid = usp.get('v') ? encodeURIComponent(usp.get('v')) : ''; + const embed = url.pathname; + if (url.origin.includes('youtu.be')) { + [, vid] = url.pathname.split('/'); + } + return `
      + +
      `; +} + +function embedVimeo(url, autoplay) { + const [, video] = url.pathname.split('/'); + const suffix = autoplay ? '?muted=1&autoplay=1' : ''; + return `
      + +
      `; +} + +function getVideoElement(source, autoplay) { + const video = document.createElement('video'); + video.setAttribute('controls', ''); + video.dataset.loading = 'true'; + video.addEventListener('loadedmetadata', () => delete video.dataset.loading); + if (autoplay) video.setAttribute('autoplay', ''); + + const sourceEl = document.createElement('source'); + sourceEl.setAttribute('src', source); + sourceEl.setAttribute('type', `video/${source.split('.').pop()}`); + video.append(sourceEl); + + return video; +} + +const loadVideoEmbed = (block, link, autoplay) => { + if (block.dataset.embedIsLoaded) { + return; + } + const url = new URL(link); + + const isYoutube = link.includes('youtube') || link.includes('youtu.be'); + const isVimeo = link.includes('vimeo'); + const isMp4 = link.includes('.mp4'); + + if (isYoutube) { + block.innerHTML = embedYoutube(url, autoplay); + } else if (isVimeo) { + block.innerHTML = embedVimeo(url, autoplay); + } else if (isMp4) { + block.textContent = ''; + block.append(getVideoElement(link, autoplay)); + } + + block.dataset.embedIsLoaded = true; +}; + +const DESKTOP_ALIGN_ENUM = { + left: 'left', + right: 'right', + center: 'center', +}; + +function positionVideoContainer(block, desktopAlign) { + block.classList.add(DESKTOP_ALIGN_ENUM[desktopAlign] || DESKTOP_ALIGN_ENUM.LEFT); +} + +export default async function decorate(block) { + block.classList.add('default-content-wrapper'); + block.closest('.section').style.padding = '0'; + const { desktopAlign } = block.closest('.section').dataset; // left / middle / right + const placeholder = block.querySelector('picture'); + const link = block.querySelector('a').href; + block.textContent = ''; + + positionVideoContainer(block, desktopAlign); + + if (placeholder) { + const wrapper = document.createElement('div'); + wrapper.className = 'video-placeholder'; + wrapper.innerHTML = '
      '; + wrapper.prepend(placeholder); + wrapper.addEventListener('click', () => { + loadVideoEmbed(block, link, true); + }); + block.append(wrapper); + } else { + block.classList.add('lazy-loading'); + const observer = new IntersectionObserver((entries) => { + if (entries.some((e) => e.isIntersecting)) { + observer.disconnect(); + loadVideoEmbed(block, link, false); + block.classList.remove('lazy-loading'); + } + }); + observer.observe(block); + } +} diff --git a/_src/blocks/webview-table/webview-table.css b/_src/blocks/webview-table/webview-table.css new file mode 100644 index 000000000..e93a500f3 --- /dev/null +++ b/_src/blocks/webview-table/webview-table.css @@ -0,0 +1,314 @@ +:root { + --first-table-cell-color: #e4f2ff; + --yes-check-color: #4A4; + --no-check-color: #FD3434; + --expandable-row-background-color: #0040F0; + --expandable-row-text-color: #fff; + --product-comparison-text-color: #5d5c5c; + --current-price-color: #000; +} + +.await-loader { + min-height: 4rem; +} + +.webview-table { + width: 100%; + height: 512px; + padding: 0 25px; + display: table; + font-size: 14px; + background-color: #141517; + color: #999; +} + +.webview-table h1 { + text-align: center; + font-size: 24px; + font-weight: 700; + font-family: "Segoe UI", Arial, sans-serif; + color: #F7F7F7; + margin: 10px 0 14px; +} + +.webview-comparison-header { + display: flex; + background-color: #141517; + border: none; +} + +.webview-table div[role="row"]{ + display: flex; +} + +.webview-comparison-header div[role="columnheader"] { + width: 142px; + text-align: center; + justify-content: center; + color: #e4f2ff; + padding-bottom: 8px; + border-right: none; + border-left: none; + + p{ + margin: 1px; + padding: 0; + line-height: 1; + } + + p:first-of-type{ + margin-top: 8px; + font-size: 14px; + } + + p:last-of-type{ + margin-bottom: 4px; + font-size: 16px; + } +} + +.webview-comparison-header div[role="columnheader"]:first-child { + min-width: 292px; +} + +.webview-table div[role='cell'] { + width: 142px; + padding: 8px; + background: #141517; + border-top: 0.1px solid #3c3c3c; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.webview-table div[role='cell']:first-child { + min-width: 292px; + max-width: 292px; + background: #333; + color: #fff; + font-weight: 600; + border-top: 1px solid black; + align-items: baseline; +} + +.webview-table .yes-check::after { + content: ''; + width: 3px; + height: 7px; + border: solid black; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.webview-table .price-box { + flex-flow: column; + color: #e4f2ff; + text-align: center; +} + +.webview-table-wrapper .webview-table .button{ + justify-content: center; + border: 2px solid #006EFF; + background-color: black; + width: 122px; + padding: 6px 16px; + border-radius: 4px; + text-align: center; + + &::after { + display: none; + content: none; + } + + &:hover span.button-text{ + transform: none; + } +} + +.webview-table .button .button-text { + color: #006EFF; + text-align: center; +} + +.webview-table-wrapper { + max-width: 770px; + height: 512px; + margin: 0 auto; + font-family: "Segoe UI", Arial, sans-serif; + + .light-mode { + background-color: #fff; + color: black; + + h1 { + color: black; + } + + .webview-comparison-header{ + background-color: #FFF; + } + + div[role="columnheader"] { + background-color: #fff; + color: #000; + } + + div[role="cell"] { + color: #515B6D; + background-color: #fff; + border-color: #F5F5F5; + + &:first-child { + color: #000; + background-color: #F9F9FE; + border-color: #FFF; + } + + .price-box { + color: black; + + .prod-oldprice{ + color: #515B6D; + } + + .prod-newprice{ + color: #000 !important; + } + } + } + + .yes-check::after { + border: solid #FFF; + border-width: 0 2px 2px 0; + } + + .button { + background-color: #fff !important; + } + + .featured{ + background-color: #F9F9FE !important; + } + + .featured .button{ + background-color: #006EFF !important; + } + } +} + +.webview-table div[role='row']:last-of-type div[role='cell'] { + border-radius: 0 0 4px 4px; + + &:first-child { + visibility: hidden; + } + + .buy-box{ + display: flex; + flex-direction: column; + gap: 0; + + .prod-oldprice{ + text-align: center; + text-decoration: line-through; + font-size: 14px; + font-family: "Segoe UI", Arial, sans-serif; + letter-spacing: 0; + opacity: 1; + } + + .prod-newprice{ + text-align: center; + font-size: 20px; + font-weight: 700; + font-family: "Segoe UI", Arial, sans-serif; + letter-spacing: 0; + color: #FFF; + opacity: 1; + line-height: 1; + } + + .under-price-text{ + font-size: 10px; + } + } +} + +.webview-table-wrapper .webview-table .button-container{ + margin-top: 2px; + margin-bottom: 4px; + + &:hover{ + filter: brightness(0.9); + } +} + +.webview-table-wrapper .webview-table .featured { + background-color: #202123; + + .button{ + background-color: #006EFF; + } + + .button-text{ + color: #FFF; + } +} + +.webview-table-wrapper .webview-table .current .button{ + border-color: #767676; + pointer-events: none; + + .button-text{ + color: #767676; + } + + &::after { + display: none; + content: none; + } +} + +.webview-table .savings-tag-container { + background-color: #2cb43d; + color: white; + font-weight: bold; + width: 100%; + border-radius: 4px 4px 0 0; + padding: 2px; +} + +.webview-table .yes-check { + width: 18px; + height: 18px; + background-color: #4CAF50; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + color: black; +} + +.webview-table .no-check { + height: 1rem; + width: 0.625rem; + position: relative; + margin-left: 7px; +} + +.webview-table .no-check::after, .webview-table .no-check::before { + content: ''; + position: absolute; + width: 0.17rem; + height: 16px; + background-color: var(--no-check-color); +} + +.webview-table .no-check::after { + transform: rotate(45deg); +} + +.webview-table .no-check::before { + transform: rotate(-45deg); +} \ No newline at end of file diff --git a/_src/blocks/webview-table/webview-table.js b/_src/blocks/webview-table/webview-table.js new file mode 100644 index 000000000..2d5169f8a --- /dev/null +++ b/_src/blocks/webview-table/webview-table.js @@ -0,0 +1,142 @@ +import { matchHeights } from '../../scripts/utils/utils.js'; + +function replaceTableTextToProperCheckmars(block) { + block.querySelectorAll('div') + .forEach(async (div) => { + if (div.textContent.match(/^yes/i)) { + div.textContent = ''; + const icon = document.createElement('div'); + icon.classList.add('yes-check'); + div.appendChild(icon); + } else if (div.textContent.match(/^no/i)) { + div.textContent = ''; + const icon = document.createElement('div'); + icon.classList.add('no-check'); + div.appendChild(icon); + } + }); +} + +function buildTableHeader(block) { + const header = block.querySelector('div:nth-of-type(2)'); + + // Ensure the header exists before trying to modify it + if (header) { + header.classList.add('webview-comparison-header'); + } +} + +function addAccesibilityRoles(block) { + block.setAttribute('role', 'table'); + const firstDiv = block.querySelector('div:first-of-type'); + [...block.querySelectorAll('div')].filter((div) => !firstDiv.contains(div)) + .forEach((div) => { + if (div.childElementCount > 1 && div.parentElement.getAttribute('role') === 'table') { + div.setAttribute('role', 'row'); + } else if (!div.hasAttribute('role')) { + div.setAttribute('role', 'cell'); + } + }); + + const header = block.querySelector('div:not(:first-child)'); + [...header.children].forEach((headerColumns) => { + headerColumns.setAttribute('role', 'columnheader'); + }); +} + +function renderPrices(block, metadata) { + const { + products, firstYearText, featuredProduct, currentProduct, saveText, + } = metadata; + + const productsAsList = Array.from(products?.split(',')); + const cells = block.querySelectorAll('div[role="cell"]'); + let index = 0; // Manual index increment + + cells.forEach((cell) => { + // Only process cells that contain the {PRICEBOX} variable + if (cell.textContent.includes('{PRICEBOX}')) { + cell.querySelector('p')?.remove(); + const [prodName, prodUsers, prodYears] = productsAsList[index]?.split('/') || []; + + const buyBox = document.createElement('div'); + buyBox.classList.add('buy-box', 'await-loader'); + + const savingsTag = document.createElement('div'); + savingsTag.style.visibility = 'hidden'; + savingsTag.classList.add('savings-tag-container'); + + // Determine if current product or featured product + const isFeatured = index + 1 === Number(featuredProduct); + const isCurrent = Number(currentProduct) === index + 1; + if (prodName && !isCurrent) { + cell.setAttribute('data-store-context', ''); + cell.setAttribute('data-store-id', prodName); + cell.setAttribute('data-store-option', `${prodUsers}-${prodYears}`); + cell.setAttribute('data-store-department', 'consumer'); + cell.setAttribute('data-store-event', 'product-loaded'); + } + // Add featured logic if applicable + if (featuredProduct && isFeatured) { + block.querySelector(`div[role="columnheader"]:nth-of-type(${Number(featuredProduct) + 1})`).classList.add('featured'); + block.querySelectorAll('div[role="row"]').forEach((row) => { + const featuredCell = row.querySelector(`div[role="cell"]:nth-of-type(${Number(featuredProduct) + 1})`); + if (featuredCell) { + featuredCell.classList.add('featured'); + } + }); + block.setAttribute('data-store-context', ''); + block.setAttribute('data-store-id', prodName); + block.setAttribute('data-store-option', `${prodUsers}-${prodYears}`); + block.setAttribute('data-store-department', 'consumer'); + block.setAttribute('data-store-event', 'product-loaded'); + savingsTag.innerHTML = ` + + ${saveText || ''} + + `; + savingsTag.style.visibility = 'visible'; + } + // Populate buy box for non-current products + if (!isCurrent) { + buyBox.innerHTML = ` +
      +
      + +
      +
      + +
      +
      + ${firstYearText} + `; + const buyLink = cell.querySelector('a[href*="#buylink"]'); + buyLink?.setAttribute('data-store-buy-link', ''); + } else { + cell.classList.add('current'); + } + + cell.insertAdjacentElement('afterbegin', buyBox); + const tagCell = block.querySelector(`div[role="columnheader"]:nth-of-type(${index + 2})`); + tagCell.insertAdjacentElement('afterbegin', savingsTag); + + // eslint-disable-next-line no-plusplus + index++; // Increment index manually + } + }); +} + +export default async function decorate(block) { + const metadata = block.closest('.section').dataset; + buildTableHeader(block); + addAccesibilityRoles(block); + replaceTableTextToProperCheckmars(block); + renderPrices(block, metadata); + matchHeights(block, '.savings-tag-container'); + matchHeights(block, '.buy-box'); + + const url = new URL(window.location.href); + if (url.searchParams.has('theme') && url.searchParams.get('theme') === 'light') { + block.classList.add('light-mode'); + } +} diff --git a/_src/blocks/webview/webview.css b/_src/blocks/webview/webview.css new file mode 100644 index 000000000..e7a28cd50 --- /dev/null +++ b/_src/blocks/webview/webview.css @@ -0,0 +1,126 @@ +.webview-wrapper { + max-width: 768px; + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + background: url("../../icons/pattern.png") repeat-x; + background-size: 188px 104px; + text-align: center; + font-family: "Segoe UI", Arial, sans-serif; + + .webview { + max-width: 438px; + margin: auto; + padding-top: 48px; + padding-bottom: 35px; + + img { + width: 92px; + height: auto; + } + + h2 { + margin-top: 16px; + font-size: 32px; + line-height: 32px; + font-weight: 700; + color: #006EFF; + } + + h3 { + margin-top: 30px; + margin-bottom: 16px; + font-size: 18px; + line-height: 24px; + font-weight: 700; + } + + .button-container { + margin-top: 14px; + margin-bottom: 0; + } + + .button { + background-color: #006EFF; + border-color: #006EFF; + color: white; + font-size: 14px; + width: 264px; + justify-content: center; + + &::after { + content: none; + } + + &:hover { + background-color: #0056CC; + border-color: #0056CC; + + span { + transform: translateX(0); + } + } + } + + .button.secondary { + background-color: white; + border-color: white; + color: #006EFF; + padding: 0; + margin: 0; + border: 0; + } + + .prod-oldprice { + font-size: var(--body-font-size-xs); + line-height: var(--body-font-size-xs); + text-decoration: line-through; + margin-right: 10px; + } + + .prod-percent { + font-size: 13px; + line-height: 15px; + color: white; + background-color: #61A851; + border-radius: 11px; + padding: 4px 10px; + font-weight: bold; + } + + .prod-newprice { + font: normal normal bold 24px / 30px; + font-family: "Segoe UI", Arial, sans-serif; + line-height: 0.7; + } + + .under-price-text { + font-size: var(--body-font-size-xxs); + line-height: var(--body-font-size-xxs); + color: #666; + + p { + margin: 0; + font-size: var(--body-font-size-xxxs); + } + } + + .price-box { + display: flex; + flex-direction: column; + gap: 9px; + } + } + + &.dark-mode { + background-color: black; + + .webview { + color: white; + + .button.secondary { + background-color: black; + border-color: black; + } + } + } +} \ No newline at end of file diff --git a/_src/blocks/webview/webview.js b/_src/blocks/webview/webview.js new file mode 100644 index 000000000..ac87e8788 --- /dev/null +++ b/_src/blocks/webview/webview.js @@ -0,0 +1,47 @@ +export default async function decorate(block) { + const { + product, saveText, + } = block.closest('.section').dataset; + + let prodName; let prodUsers; let prodYears; + if (product) { + [prodName, prodUsers, prodYears] = product.split('/'); + } + block.setAttribute('data-store-context', ''); + block.setAttribute('data-store-id', prodName); + block.setAttribute('data-store-option', `${prodUsers}-${prodYears}`); + block.setAttribute('data-store-department', 'consumer'); + block.setAttribute('data-store-event', 'product-loaded'); + + const buyLink = block.querySelector('a[href*="#buylink"]'); + buyLink?.setAttribute('data-store-buy-link', ''); + + [...block.children].forEach((child) => { + if (child.textContent.includes('{PRICE_BOX}') && product) { + child.innerHTML = child.innerHTML.replace('{PRICE_BOX}', '
      Price box
      '); + child.innerHTML = ` +
      +
      + + ${saveText || ''} +
      +
      + +
      +
      `; + } + if (child.textContent.includes('{under_price_text}')) { + // remove the p tag that is wrapping the text {under_price_text} + child.querySelector('p')?.remove(); + + child.classList.add('under-price-text'); + } + }); + + const url = new URL(window.location.href); + if (url.searchParams.has('theme') && url.searchParams.get('theme') === 'dark') { + block.parentElement.classList.add('dark-mode'); + } + + block.querySelector('a').setAttribute('target', '_blank'); +} diff --git a/_src/fonts/ibm-plex-sans-300.woff2 b/_src/fonts/ibm-plex-sans-300.woff2 new file mode 100644 index 000000000..5eb6300c8 Binary files /dev/null and b/_src/fonts/ibm-plex-sans-300.woff2 differ diff --git a/_src/fonts/ibm-plex-sans-400.woff2 b/_src/fonts/ibm-plex-sans-400.woff2 new file mode 100644 index 000000000..8e1333308 Binary files /dev/null and b/_src/fonts/ibm-plex-sans-400.woff2 differ diff --git a/_src/fonts/ibm-plex-sans-500.woff2 b/_src/fonts/ibm-plex-sans-500.woff2 new file mode 100644 index 000000000..1b3f5c649 Binary files /dev/null and b/_src/fonts/ibm-plex-sans-500.woff2 differ diff --git a/solutions/fonts/roboto-300.woff2 b/_src/fonts/roboto-300.woff2 similarity index 100% rename from solutions/fonts/roboto-300.woff2 rename to _src/fonts/roboto-300.woff2 diff --git a/solutions/fonts/roboto-400.woff2 b/_src/fonts/roboto-400.woff2 similarity index 100% rename from solutions/fonts/roboto-400.woff2 rename to _src/fonts/roboto-400.woff2 diff --git a/solutions/fonts/roboto-500.woff2 b/_src/fonts/roboto-500.woff2 similarity index 100% rename from solutions/fonts/roboto-500.woff2 rename to _src/fonts/roboto-500.woff2 diff --git a/_src/icons/arow_down.png b/_src/icons/arow_down.png new file mode 100644 index 000000000..194b19a3b Binary files /dev/null and b/_src/icons/arow_down.png differ diff --git a/solutions/icons/arrow-right.svg b/_src/icons/arrow-right.svg similarity index 100% rename from solutions/icons/arrow-right.svg rename to _src/icons/arrow-right.svg diff --git a/_src/icons/b-logo-red.svg b/_src/icons/b-logo-red.svg new file mode 100644 index 000000000..14d05cb41 --- /dev/null +++ b/_src/icons/b-logo-red.svg @@ -0,0 +1 @@ + diff --git a/_src/icons/bd-round-thumb.svg b/_src/icons/bd-round-thumb.svg new file mode 100644 index 000000000..102b37c76 --- /dev/null +++ b/_src/icons/bd-round-thumb.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/solutions/icons/blue-circle.svg b/_src/icons/blue-circle.svg similarity index 100% rename from solutions/icons/blue-circle.svg rename to _src/icons/blue-circle.svg diff --git a/_src/icons/book-sharp-regular.svg b/_src/icons/book-sharp-regular.svg new file mode 100644 index 000000000..2c2316457 --- /dev/null +++ b/_src/icons/book-sharp-regular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/bulb-pink.svg b/_src/icons/bulb-pink.svg new file mode 100644 index 000000000..039b32ce8 --- /dev/null +++ b/_src/icons/bulb-pink.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/_src/icons/bulb.svg b/_src/icons/bulb.svg new file mode 100644 index 000000000..eae75151f --- /dev/null +++ b/_src/icons/bulb.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/_src/icons/burger_menu.JPG b/_src/icons/burger_menu.JPG new file mode 100644 index 000000000..3743e7ef1 Binary files /dev/null and b/_src/icons/burger_menu.JPG differ diff --git a/_src/icons/check.svg b/_src/icons/check.svg new file mode 100644 index 000000000..7334b94de --- /dev/null +++ b/_src/icons/check.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/_src/icons/checkmark-green-circle.svg b/_src/icons/checkmark-green-circle.svg new file mode 100644 index 000000000..de0d9ec77 --- /dev/null +++ b/_src/icons/checkmark-green-circle.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/solutions/icons/checkmark_solid-circle.svg b/_src/icons/checkmark-light-green-circle.svg similarity index 100% rename from solutions/icons/checkmark_solid-circle.svg rename to _src/icons/checkmark-light-green-circle.svg diff --git a/solutions/icons/checkmark-solid-circle-white.svg b/_src/icons/checkmark-solid-circle-white.svg similarity index 100% rename from solutions/icons/checkmark-solid-circle-white.svg rename to _src/icons/checkmark-solid-circle-white.svg diff --git a/_src/icons/checkmark-x-circle.svg b/_src/icons/checkmark-x-circle.svg new file mode 100644 index 000000000..ed5ad8c7d --- /dev/null +++ b/_src/icons/checkmark-x-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/checkmark_solid-circle.svg b/_src/icons/checkmark_solid-circle.svg new file mode 100644 index 000000000..151ed5733 --- /dev/null +++ b/_src/icons/checkmark_solid-circle.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/_src/icons/close_x.JPG b/_src/icons/close_x.JPG new file mode 100644 index 000000000..f5067718a Binary files /dev/null and b/_src/icons/close_x.JPG differ diff --git a/solutions/icons/dark-blue-quote.svg b/_src/icons/dark-blue-quote.svg similarity index 100% rename from solutions/icons/dark-blue-quote.svg rename to _src/icons/dark-blue-quote.svg diff --git a/_src/icons/facebook.svg b/_src/icons/facebook.svg new file mode 100644 index 000000000..ff4c4a0e7 --- /dev/null +++ b/_src/icons/facebook.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/_src/icons/green-shield.svg b/_src/icons/green-shield.svg new file mode 100644 index 000000000..eba143758 --- /dev/null +++ b/_src/icons/green-shield.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_src/icons/illustration-malware.svg b/_src/icons/illustration-malware.svg new file mode 100644 index 000000000..d33a59fd2 --- /dev/null +++ b/_src/icons/illustration-malware.svg @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_src/icons/link-checker-example.svg b/_src/icons/link-checker-example.svg new file mode 100644 index 000000000..6cdb9b8b7 --- /dev/null +++ b/_src/icons/link-checker-example.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/_src/icons/link-checker-pattern-green.svg b/_src/icons/link-checker-pattern-green.svg new file mode 100644 index 000000000..e4e1dab21 --- /dev/null +++ b/_src/icons/link-checker-pattern-green.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_src/icons/link-checker-pattern-red.svg b/_src/icons/link-checker-pattern-red.svg new file mode 100644 index 000000000..3ba9626d2 --- /dev/null +++ b/_src/icons/link-checker-pattern-red.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_src/icons/link-checker-pattern.svg b/_src/icons/link-checker-pattern.svg new file mode 100644 index 000000000..ef9e1ee76 --- /dev/null +++ b/_src/icons/link-checker-pattern.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_src/icons/linkedin.svg b/_src/icons/linkedin.svg new file mode 100644 index 000000000..c731c259f --- /dev/null +++ b/_src/icons/linkedin.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_src/icons/minus-sharp-regular.svg b/_src/icons/minus-sharp-regular.svg new file mode 100644 index 000000000..81c865a81 --- /dev/null +++ b/_src/icons/minus-sharp-regular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/no-response.svg b/_src/icons/no-response.svg new file mode 100644 index 000000000..9da6bc625 --- /dev/null +++ b/_src/icons/no-response.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/_src/icons/particle-band.svg b/_src/icons/particle-band.svg new file mode 100644 index 000000000..589d18298 --- /dev/null +++ b/_src/icons/particle-band.svg @@ -0,0 +1 @@ + diff --git a/_src/icons/pattern.png b/_src/icons/pattern.png new file mode 100644 index 000000000..8a4221d6a Binary files /dev/null and b/_src/icons/pattern.png differ diff --git a/_src/icons/plus-sharp-regular.svg b/_src/icons/plus-sharp-regular.svg new file mode 100644 index 000000000..395763b64 --- /dev/null +++ b/_src/icons/plus-sharp-regular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/quot.png b/_src/icons/quot.png new file mode 100644 index 000000000..c5d74ede4 Binary files /dev/null and b/_src/icons/quot.png differ diff --git a/_src/icons/quote-left.svg b/_src/icons/quote-left.svg new file mode 100644 index 000000000..a98b2aa46 --- /dev/null +++ b/_src/icons/quote-left.svg @@ -0,0 +1 @@ + diff --git a/_src/icons/safe.svg b/_src/icons/safe.svg new file mode 100644 index 000000000..468893b2c --- /dev/null +++ b/_src/icons/safe.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/solutions/icons/search.svg b/_src/icons/search.svg similarity index 100% rename from solutions/icons/search.svg rename to _src/icons/search.svg diff --git a/_src/icons/share.svg b/_src/icons/share.svg new file mode 100644 index 000000000..01091adb3 --- /dev/null +++ b/_src/icons/share.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/solutions/icons/tabs_arrow.svg b/_src/icons/tabs_arrow.svg similarity index 100% rename from solutions/icons/tabs_arrow.svg rename to _src/icons/tabs_arrow.svg diff --git a/_src/icons/twitter.svg b/_src/icons/twitter.svg new file mode 100644 index 000000000..91888f30f --- /dev/null +++ b/_src/icons/twitter.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/_src/icons/user-guide-white.svg b/_src/icons/user-guide-white.svg new file mode 100644 index 000000000..947acceb9 --- /dev/null +++ b/_src/icons/user-guide-white.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/solutions/icons/user-guide.svg b/_src/icons/user-guide.svg similarity index 100% rename from solutions/icons/user-guide.svg rename to _src/icons/user-guide.svg diff --git a/_src/icons/youtube.svg b/_src/icons/youtube.svg new file mode 100644 index 000000000..731648bb4 --- /dev/null +++ b/_src/icons/youtube.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/_src/images/appstore.webp b/_src/images/appstore.webp new file mode 100644 index 000000000..029cf0a47 Binary files /dev/null and b/_src/images/appstore.webp differ diff --git a/solutions/images/b-red-mask.png b/_src/images/b-red-mask.png similarity index 100% rename from solutions/images/b-red-mask.png rename to _src/images/b-red-mask.png diff --git a/_src/images/black_company_logo.svg b/_src/images/black_company_logo.svg new file mode 100644 index 000000000..485f5412a --- /dev/null +++ b/_src/images/black_company_logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/_src/images/playstore.webp b/_src/images/playstore.webp new file mode 100644 index 000000000..dbe58b8b4 Binary files /dev/null and b/_src/images/playstore.webp differ diff --git a/_src/images/quiz-results-bg.jpg b/_src/images/quiz-results-bg.jpg new file mode 100644 index 000000000..50f80d497 Binary files /dev/null and b/_src/images/quiz-results-bg.jpg differ diff --git a/_src/images/sigla_bd_white.svg b/_src/images/sigla_bd_white.svg new file mode 100644 index 000000000..23ab4e9f2 --- /dev/null +++ b/_src/images/sigla_bd_white.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/_src/plugins/experimentation/CODE_OF_CONDUCT.md b/_src/plugins/experimentation/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/plugins/experimentation/LICENSE.md b/_src/plugins/experimentation/LICENSE.md similarity index 100% rename from solutions/plugins/experimentation/LICENSE.md rename to _src/plugins/experimentation/LICENSE.md diff --git a/solutions/plugins/experimentation/README.md b/_src/plugins/experimentation/README.md similarity index 100% rename from solutions/plugins/experimentation/README.md rename to _src/plugins/experimentation/README.md diff --git a/solutions/plugins/experimentation/package-lock.json b/_src/plugins/experimentation/package-lock.json similarity index 100% rename from solutions/plugins/experimentation/package-lock.json rename to _src/plugins/experimentation/package-lock.json diff --git a/solutions/plugins/experimentation/package.json b/_src/plugins/experimentation/package.json similarity index 100% rename from solutions/plugins/experimentation/package.json rename to _src/plugins/experimentation/package.json diff --git a/solutions/plugins/experimentation/src/index.js b/_src/plugins/experimentation/src/index.js similarity index 100% rename from solutions/plugins/experimentation/src/index.js rename to _src/plugins/experimentation/src/index.js diff --git a/solutions/plugins/experimentation/src/preview.css b/_src/plugins/experimentation/src/preview.css similarity index 100% rename from solutions/plugins/experimentation/src/preview.css rename to _src/plugins/experimentation/src/preview.css diff --git a/solutions/plugins/experimentation/src/preview.js b/_src/plugins/experimentation/src/preview.js similarity index 100% rename from solutions/plugins/experimentation/src/preview.js rename to _src/plugins/experimentation/src/preview.js diff --git a/solutions/plugins/experimentation/src/ued.js b/_src/plugins/experimentation/src/ued.js similarity index 100% rename from solutions/plugins/experimentation/src/ued.js rename to _src/plugins/experimentation/src/ued.js diff --git a/solutions/plugins/rum-conversion/.eslintignore b/_src/plugins/rum-conversion/.eslintignore similarity index 100% rename from solutions/plugins/rum-conversion/.eslintignore rename to _src/plugins/rum-conversion/.eslintignore diff --git a/solutions/plugins/experimentation/.eslintrc.js b/_src/plugins/rum-conversion/.eslintrc.js similarity index 100% rename from solutions/plugins/experimentation/.eslintrc.js rename to _src/plugins/rum-conversion/.eslintrc.js diff --git a/solutions/plugins/rum-conversion/.gitignore b/_src/plugins/rum-conversion/.gitignore similarity index 100% rename from solutions/plugins/rum-conversion/.gitignore rename to _src/plugins/rum-conversion/.gitignore diff --git a/solutions/plugins/rum-conversion/.npmignore b/_src/plugins/rum-conversion/.npmignore similarity index 100% rename from solutions/plugins/rum-conversion/.npmignore rename to _src/plugins/rum-conversion/.npmignore diff --git a/solutions/plugins/experimentation/.stylelintrc.json b/_src/plugins/rum-conversion/.stylelintrc.json similarity index 100% rename from solutions/plugins/experimentation/.stylelintrc.json rename to _src/plugins/rum-conversion/.stylelintrc.json diff --git a/solutions/plugins/rum-conversion/LICENSE b/_src/plugins/rum-conversion/LICENSE similarity index 100% rename from solutions/plugins/rum-conversion/LICENSE rename to _src/plugins/rum-conversion/LICENSE diff --git a/solutions/plugins/rum-conversion/README.md b/_src/plugins/rum-conversion/README.md similarity index 100% rename from solutions/plugins/rum-conversion/README.md rename to _src/plugins/rum-conversion/README.md diff --git a/solutions/plugins/rum-conversion/package-lock.json b/_src/plugins/rum-conversion/package-lock.json similarity index 100% rename from solutions/plugins/rum-conversion/package-lock.json rename to _src/plugins/rum-conversion/package-lock.json diff --git a/solutions/plugins/rum-conversion/package.json b/_src/plugins/rum-conversion/package.json similarity index 100% rename from solutions/plugins/rum-conversion/package.json rename to _src/plugins/rum-conversion/package.json diff --git a/solutions/plugins/rum-conversion/src/index.js b/_src/plugins/rum-conversion/src/index.js similarity index 100% rename from solutions/plugins/rum-conversion/src/index.js rename to _src/plugins/rum-conversion/src/index.js diff --git a/solutions/scripts/breadcrumbs.js b/_src/scripts/breadcrumbs.js similarity index 80% rename from solutions/scripts/breadcrumbs.js rename to _src/scripts/breadcrumbs.js index 0a701a416..716e3effb 100644 --- a/solutions/scripts/breadcrumbs.js +++ b/_src/scripts/breadcrumbs.js @@ -2,17 +2,16 @@ import { createTag, fetchIndex, fixExcelFilterZeroes, -} from './utils.js'; - -// eslint-disable-next-line import/no-cycle -import { decorateBlockWithRegionId } from './scripts.js'; + getDomain, + decorateBlockWithRegionId, +} from './utils/utils.js'; function prependSlash(path) { return path.startsWith('/') ? path : `/${path}`; } function getName(pageIndex, path, part, current) { - const pg = pageIndex.find((page) => page.path === path); + const pg = pageIndex.find((page) => page.path.replace(/^\/[^/]+/, '') === path.replace(/^\/[^/]+/, '')); if (pg && pg.breadcrumbtitle && pg.breadcrumbtitle !== '0') { return pg.breadcrumbtitle; } @@ -40,7 +39,8 @@ async function createBreadcrumbs(container) { const { pathname } = window.location; const pathSeparator = '/'; // split pathname into parts add / at the end and remove empty parts - const pathSplit = pathname.split('/').reduce((acc, curr, index, array) => { + const domain = getDomain(); + const pathSplit = pathname.split('/').filter((item) => item !== domain).reduce((acc, curr, index, array) => { if (index < array.length - 1) { acc.push(`${curr}/`); } else if (curr !== '') { @@ -57,19 +57,19 @@ async function createBreadcrumbs(container) { const breadcrumbs = [ { name: 'Home', - url_path: '/', + url_path: `/${domain}/`, }, ...pathSplit.slice(1, -1).map((part, index) => { const url = urlForIndex(index); return { - name: getName(pageIndex, url, part, false), - url_path: url, + name: getName(pageIndex, `/${domain}${url}`, part, false, domain), + url_path: `/${domain}${url}`, }; }), { // get the breadcrumb title from the metadata; if the metadata does not contain it, // the last part of the path is used as the breadcrumb title - name: getName(pageIndex, pathname, pathSplit[pathSplit.length - 1], true), + name: getName(pageIndex, pathname, pathSplit[pathSplit.length - 1], true, domain), }, ]; diff --git a/_src/scripts/delayed.js b/_src/scripts/delayed.js new file mode 100644 index 000000000..2b6e6dc09 --- /dev/null +++ b/_src/scripts/delayed.js @@ -0,0 +1,24 @@ +// eslint-disable-next-line import/no-cycle +import { + sampleRUM, + getMetadata, +} from './lib-franklin.js'; + +import { loadBreadcrumbs } from './breadcrumbs.js'; +import { openUrlForOs } from './utils/utils.js'; + +// Core Web Vitals RUM collection +sampleRUM('cwv'); + +// Load breadcrumbs +loadBreadcrumbs(); + +// Get the open URL for the user's OS +const urlMacos = getMetadata('open-url-macos'); +const urlWindows = getMetadata('open-url-windows'); +const urlAndroid = getMetadata('open-url-android'); +const urlIos = getMetadata('open-url-ios'); + +if (urlMacos || urlWindows || urlAndroid || urlIos) { + openUrlForOs(urlMacos, urlWindows, urlAndroid, urlIos); +} diff --git a/_src/scripts/lib-franklin-api.js b/_src/scripts/lib-franklin-api.js new file mode 100644 index 000000000..7cfa9d3f0 --- /dev/null +++ b/_src/scripts/lib-franklin-api.js @@ -0,0 +1,264 @@ +/** + * @param {HTMLDivElement} shadoRoot + * @param {string} origin - prepends the origin to the relative links + */ +const updateLinkSources = (shadoRoot, origin) => { + shadoRoot + .querySelectorAll('source') + .forEach(source => source.srcset = new URL(source.getAttribute("srcset"), origin).href); + + shadoRoot + .querySelectorAll('img') + .forEach(image => image.src = new URL(image.getAttribute("src"), origin).href); +}; + +let ICONS_CACHE = {}; +async function decorateIcons(element) { + // Prepare the inline sprite + let svgSprite = element.getElementById('franklin-svg-sprite'); + if (!svgSprite) { + const div = document.createElement('div'); + div.innerHTML = ''; + svgSprite = div.firstElementChild; + element.append(div.firstElementChild); + } + // Download all new icons + const icons = [...element.querySelectorAll('span.icon')]; + await Promise.all(icons.map(async (span) => { + const iconName = Array.from(span.classList).find((c) => c.startsWith('icon-')).substring(5); + if (!ICONS_CACHE[iconName]) { + ICONS_CACHE[iconName] = true; + try { + let dynamicIconsSharepointPath = 'https://www.bitdefender.com/common/icons/'; + if (window.location.hostname.includes('bitdefender.co.uk')) { + dynamicIconsSharepointPath = 'https://www.bitdefender.co.uk/content/dam/franklin/'; + } + if (window.location.hostname.includes('bitdefender.fr')) { + dynamicIconsSharepointPath = 'https://www.bitdefender.fr/content/dam/franklin/'; + } + // check for localhost + if (window.location.hostname === 'localhost') { + dynamicIconsSharepointPath = 'https://www.bitdefender.com/common/icons/'; + } + const response = await fetch(`${dynamicIconsSharepointPath}${iconName}.svg`); + if (!response.ok) { + ICONS_CACHE[iconName] = false; + return; + } + // Styled icons don't play nice with the sprite approach because of shadow dom isolation + const svg = await response.text(); + if (svg.match(/(