diff --git a/blocks/footer/footer.css b/blocks/footer/footer.css index 9e8122f4..1e7e9a4d 100644 --- a/blocks/footer/footer.css +++ b/blocks/footer/footer.css @@ -184,7 +184,7 @@ .footer-list .footer__title:not(.expand):focus, .footer-list-item a:focus, .footer-bar a:focus { - outline: 2px solid var(--light-border-focus); + outline: 2px solid var(--border-focus); } button.v2-scroll-to-top:focus { @@ -192,7 +192,7 @@ button.v2-scroll-to-top:focus { } .v2-scroll-to-top:focus-visible { - outline: 2px solid var(--light-border-focus); + outline: 2px solid var(--border-focus); outline-offset: 1px; } @@ -230,7 +230,7 @@ button.v2-scroll-to-top:focus { gap: 20px } - .footer-list, + .footer-list, .footer-list-item { display: flex; flex-direction: column; @@ -247,7 +247,7 @@ button.v2-scroll-to-top:focus { max-height: 100%; overflow: auto; } - + .footer-list-item a { gap: 8px; align-items: center; diff --git a/blocks/v2-event-notify/v2-event-notify.css b/blocks/v2-event-notify/v2-event-notify.css new file mode 100644 index 00000000..1d3cbf3f --- /dev/null +++ b/blocks/v2-event-notify/v2-event-notify.css @@ -0,0 +1,176 @@ +.v2-event-notify__container > * { + max-width: 694px; + margin: auto; +} + +.v2-event-notify__container .v2-event-notify__text-wrapper { + display: flex; + flex-direction: column; + gap: 8px; + text-align: center; + max-width: var(--text-block-max-width); + margin: 40px auto; +} + +.v2-event-notify__container .v2-event-notify__title { + font-size: var(--f-heading-4-font-size); + letter-spacing: var(--f-heading-4-letter-spacing); + line-height: var(--f-heading-4-line-height); + margin: 0; +} + +.v2-event-notify__container .v2-event-notify__text-wrapper p { + margin: 0; +} + +.v2-event-notify__container .event-notify__wrapper { + display: flex; + flex-direction: column; + gap: 16px; +} + +.v2-event-notify__container .event-notify__field-wrapper { + display: flex; + flex-direction: column; + gap: 8px; +} + +.v2-event-notify__container .v2-forms__container input { + background: var(--c-primary-white); + font-size: var(--f-body-font-size); + letter-spacing: var(--f-body-letter-spacing); + line-height: var(--f-body-line-height); + margin: 0; +} + +.v2-event-notify__container .event-notify__buttons { + gap: 24px; + display: flex; + flex-direction: column; + align-items: center; +} + +.v2-event-notify__container .event-notify__agreement-section { + display: flex; + flex-direction: column; + gap: 8px; + margin-top: 40px; +} + +.v2-event-notify__container .event-notify__error-message { + color: var(--c-error-red); + font-size: var(--f-caption-font-size); + line-height: var(--f-caption-line-height); + letter-spacing: var(--f-caption-letter-spacing); +} + +.v2-event-notify__container .v2-event-notify__message-text { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + padding: 40px 0; + text-align: center; + max-width: 506px; +} + +.v2-event-notify__container .v2-event-notify__message-text p { + margin: 0; +} + +.v2-event-notify__container .v2-event-notify__button-wrapper { + display: flex; + justify-content: center; + margin-bottom: 40px; +} + +.v2-event-notify__container .v2-social-block { + max-width: unset; +} + +.v2-event-notify__container input:user-invalid, +.v2-event-notify__container input:user-invalid:hover, +.v2-event-notify__container input:user-invalid:focus { + border-color: var(--c-error-red); +} + +.v2-event-notify__container .event-notify__add-event-button { + cursor: pointer; +} + +.event-notify__policy { + margin: 16px 0 32px; +} + +@media (min-width: 744px) { + .v2-event-notify__container .event-notify__wrapper { + display: flex; + flex-flow: row wrap; + } + + .v2-event-notify__container .event-notify__wrapper > * { + width: calc(50% - 8px); + } + + .v2-event-notify__container .v2-event-notify__text-wrapper { + gap: 16px; + } + + .v2-event-notify__container .event-notify__agreement-section { + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + } + + .v2-event-notify__container .event-notify__buttons { + flex-direction: row; + justify-content: center; + } + + .v2-event-notify__container .v2-event-notify__message-text { + gap: 16px; + } +} + +@media (min-width: 1200px) { + .v2-event-notify__container .v2-event-notify__text-wrapper { + margin: 48px auto; + gap: 24px; + } + + .v2-event-notify__container .v2-event-notify__title { + font-size: var(--f-heading-3-font-size); + letter-spacing: var(--f-heading-3-letter-spacing); + line-height: var(--f-heading-3-line-height); + margin: 0; + } + + .v2-event-notify__container .v2-event-notify__text-wrapper p { + font-size: var(--f-body-2-font-size); + letter-spacing: var(--f-body-2-letter-spacing); + line-height: var(--f-body-2-line-height); + } + + .v2-event-notify__container .event-notify__wrapper { + column-gap: 20px; + row-gap: 24px; + } + + .v2-event-notify__container .event-notify__wrapper > * { + width: calc(50% - 10px); + } + + .v2-event-notify__container .event-notify__agreement-section { + margin-top: 48px; + } + + .v2-event-notify__container .v2-event-notify__message-text { + gap: 24px; + padding: 48px 0; + } + + .v2-event-notify__container .v2-event-notify__button-wrapper { + margin-bottom: 48px; + } +} diff --git a/blocks/v2-event-notify/v2-event-notify.js b/blocks/v2-event-notify/v2-event-notify.js new file mode 100644 index 00000000..baeea051 --- /dev/null +++ b/blocks/v2-event-notify/v2-event-notify.js @@ -0,0 +1,188 @@ +import { + loadBlock, sampleRUM, +} from '../../scripts/lib-franklin.js'; +import { + createElement, +} from '../../scripts/common.js'; + +const blockName = 'v2-event-notify'; + +let successText; +let errorText; +let socialsLinks; + +const onSuccess = async () => { + sampleRUM('form:submit'); + const block = document.querySelector(`.${blockName}__container`); + const addToEventButton = block.querySelector('.event-notify__add-event-button'); + + block.innerHTML = ''; + const buttonWrapper = createElement('div', { classes: `${blockName}__button-wrapper` }); + addToEventButton.classList.remove('secondary'); + addToEventButton.classList.add('primary'); + + const socialsLinksBlock = document.createRange().createContextualFragment(` +
+
+
+
+
`); + + const socialLinkBlockEl = socialsLinksBlock.children[0]; + socialLinkBlockEl.querySelector(':scope > div > div').innerHTML = socialsLinks.innerHTML; + + await loadBlock(socialLinkBlockEl); + + buttonWrapper.append(addToEventButton); + block.append(successText, buttonWrapper, socialLinkBlockEl); +}; + +const onError = (error) => { + // eslint-disable-next-line no-console + console.error(error); + + const block = document.querySelector(`.${blockName}__container`); + + block.innerHTML = ''; + block.append(errorText); +}; + +// Convert date to ICS format (e.g., 20231210T120000Z) +function formatDateToICS(date) { + return date.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, ''); +} + +// Generate UID (e.g., 20231210T120000Z-sdfijk@exmaple.com) +function generateUID() { + const timestamp = formatDateToICS(new Date()); + const uniqueString = Math.random().toString(36).substr(2, 6); + const domain = window.location.hostname; + return `${timestamp}-${uniqueString}@${domain}`; +} + +function generateICS(event) { + if (!event.summary || !event.startDate || !event.endDate || !event.description) { + throw new Error('Missing required event details'); + } + const icsData = [ + 'BEGIN:VCALENDAR', + 'VERSION:2.0', + 'PRODID:-//Volvo Trucks//Volvo Trucks US website//EN', + `UID:${generateUID()}`, + 'BEGIN:VEVENT', + `SUMMARY:${event.summary}`, + `DTSTART:${formatDateToICS(event.startDate)}`, + `DTEND:${formatDateToICS(event.endDate)}`, + `DESCRIPTION:${event.description}`, + 'LOCATION:online', + 'END:VEVENT', + 'END:VCALENDAR', + ].join('\r\n'); + return icsData; +} + +function downloadICSFile(icsData, filename) { + const blob = new Blob([icsData], { type: 'text/calendar' }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = filename; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); +} + +window.logResult = function logResult(json) { + if (json.result === 'success') { + onSuccess(); + } else if (json.result === 'error') { + onError(json.log); + } +}; + +export default async function decorate(block) { + const rows = [...block.querySelectorAll(':scope > div')]; + + const contentData = rows.reduce((data, row) => { + const [name, content] = row.querySelectorAll(':scope > div'); + const key = name.innerText.toLowerCase().trim(); + + return { ...data, [key]: content }; + }, {}); + + const formLink = contentData.link.innerText.trim(); + const beforeFormText = contentData['before form']; + const policyText = contentData.policy; + socialsLinks = contentData.socials; + socialsLinks.classList.add(`${blockName}__socials`); + errorText = contentData['error message']; + errorText.classList.add(`${blockName}__message-text`); + successText = contentData['success message']; + successText.classList.add(`${blockName}__message-text`); + + // Calendar event meta data + const blockSection = block.parentElement?.parentElement; + const calendarEventData = { + summary: blockSection?.dataset.eventSummary, + startDate: new Date(blockSection?.dataset.eventStartDate), + endDate: new Date(blockSection?.dataset.eventEndDate), + description: blockSection?.dataset.eventDescription, + }; + + const container = createElement('div', { classes: `${blockName}__container` }); + const formContainer = createElement('div', { classes: `${blockName}__form-container` }); + const form = document.createRange().createContextualFragment(` +
+
+
event-notify
+
+
+
${formLink}
+
+
`); + + if (beforeFormText) { + container.append(beforeFormText); + beforeFormText.classList.add(`${blockName}__text-wrapper`); + + const headingSelector = 'h1, h2, h3, h4, h5, h6'; + const headings = [ + ...beforeFormText.querySelectorAll(headingSelector), + ...errorText.querySelectorAll(headingSelector), + ...successText.querySelectorAll(headingSelector), + ]; + headings.forEach((heading) => heading.classList.add(`${blockName}__title`)); + } + formContainer.append(...form.children); + container.appendChild(formContainer); + + block.replaceWith(container); + + // we can inject the policy content when form content loaded + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + const formRef = [...mutation.addedNodes]; + const policyEl = formRef.find((el) => el.querySelector('.event-notify__policy'))?.querySelector('.event-notify__policy'); + const calendarButtonEl = formRef.find((el) => el.querySelector('.event-notify__add-event-button'))?.querySelector('.event-notify__add-event-button'); + + if (formRef) { + policyEl.append(policyText); + calendarButtonEl.addEventListener('click', () => { + const icsFileContent = generateICS(calendarEventData); + downloadICSFile(icsFileContent, 'event.ics'); + }); + + observer.disconnect(); + } + }); + }); + + observer.observe(container, { + childList: true, + attributes: false, + subtree: true, + }); + + await loadBlock(formContainer.firstElementChild); +} diff --git a/blocks/v2-forms/forms/event-notify.js b/blocks/v2-forms/forms/event-notify.js new file mode 100644 index 00000000..32447b30 --- /dev/null +++ b/blocks/v2-forms/forms/event-notify.js @@ -0,0 +1,77 @@ +import { getTextLabel } from '../../../scripts/common.js'; + +const formName = 'event-notify'; +const formContent = ` +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+ + + +
+
+
+
+ +
+ + ${getTextLabel('event-notify:add-event')} +
+`; + +const checkFieldValidity = (field) => { + const errorMessageEl = field.parentElement.querySelector(`:scope > .${formName}__error-message`); + + if (errorMessageEl) { + const isUserInvalid = field.parentElement.querySelector(':scope:user-invalid') === field; + errorMessageEl.innerText = isUserInvalid ? '' : field.validationMessage; + errorMessageEl.classList[isUserInvalid ? 'add' : 'remove'](`${formName}__error-message--hidden`); + } +}; + +export const postLoad = (form) => { + form.setAttribute('novalidate', 'novalidate'); + + const fields = [...form.querySelectorAll('input')]; + + fields.forEach((field) => { + field.addEventListener('input', () => { + checkFieldValidity(field); + }); + }); +}; + +export const onSubmit = async (form, handleSubmit) => { + const fields = [...form.querySelectorAll('input')]; + + fields.forEach(checkFieldValidity); + + if (form.checkValidity()) { + await handleSubmit(form); + } +}; + +export default formContent; diff --git a/blocks/v2-forms/v2-forms.js b/blocks/v2-forms/v2-forms.js index e0be3890..1bd7b495 100644 --- a/blocks/v2-forms/v2-forms.js +++ b/blocks/v2-forms/v2-forms.js @@ -33,13 +33,18 @@ async function prepareRequest(form) { const url = form.dataset.action; const serializedData = serialize(payload); - loadScript(`${url}?${serializedData}`, { type: 'text/javascript', charset: 'UTF-8' }); + + return loadScript(`${url}?${serializedData}`, { type: 'text/javascript', charset: 'UTF-8' }); } async function handleSubmit(form) { if (form.getAttribute('data-submitting') !== 'true') { form.setAttribute('data-submitting', 'true'); - await prepareRequest(form); + try { + await prepareRequest(form); + } catch (error) { + window.logResult({ result: 'success', log: error }); + } } } @@ -83,6 +88,12 @@ const addForm = async (block) => { const formObj = document.querySelector('form'); // eslint-disable-next-line prefer-destructuring formObj.addEventListener('submit', (e) => { + if (formContent.onSubmit) { + e.preventDefault(); + formObj.dataset.action = e.currentTarget.action; + formContent.onSubmit(formObj, handleSubmit); + } + let isValid = true; if (formObj.hasAttribute('novalidate')) { isValid = formObj.checkValidity(); @@ -91,9 +102,12 @@ const addForm = async (block) => { if (isValid) { e.submitter.setAttribute('disabled', ''); formObj.dataset.action = e.currentTarget.action; + handleSubmit(formObj); } }); + + formContent.postLoad?.(formObj); }; export default async function decorate(block) { diff --git a/blocks/v2-inpage-navigation/v2-inpage-navigation.css b/blocks/v2-inpage-navigation/v2-inpage-navigation.css index 54fa31a2..df929f04 100644 --- a/blocks/v2-inpage-navigation/v2-inpage-navigation.css +++ b/blocks/v2-inpage-navigation/v2-inpage-navigation.css @@ -106,7 +106,7 @@ then we change it for the next section item in main */ } .v2-inpage-navigation__items-close:focus-visible { - outline: 2px solid var(--light-border-focus); + outline: 2px solid var(--border-focus); } .v2-inpage-navigation__dropdown-title { diff --git a/blocks/v2-media-with-tabs/v2-media-with-tabs.css b/blocks/v2-media-with-tabs/v2-media-with-tabs.css index eeec93ba..6b37f917 100644 --- a/blocks/v2-media-with-tabs/v2-media-with-tabs.css +++ b/blocks/v2-media-with-tabs/v2-media-with-tabs.css @@ -85,7 +85,7 @@ button.v2-media-with-tabs__tab:focus { } button.v2-media-with-tabs__tab:focus-visible { - outline: 2px solid var(--light-border-focus); + outline: 2px solid var(--border-focus); outline-offset: 5px; } @@ -110,7 +110,7 @@ button.v2-media-with-tabs__tab:focus-visible { .v2-media-with-tabs__tabs-section { padding: 32px 0; } - + .v2-media-with-tabs__header-section { width: 50%; } @@ -143,7 +143,7 @@ button.v2-media-with-tabs__tab:focus-visible { .v2-media-with-tabs.v2-media-with-tabs--media-right { padding: 0 32px 0 64px; } - + .v2-media-with-tabs--media-right .v2-media-with-tabs__images-section { order: 2; } @@ -162,7 +162,7 @@ button.v2-media-with-tabs__tab:focus-visible { margin-bottom: 48px; font-size: var(--f-body-2-font-size); } - + .v2-media-with-tabs__image img { max-height: unset; } @@ -182,5 +182,5 @@ button.v2-media-with-tabs__tab:focus-visible { order: 1; width: 100%; } - + } diff --git a/blocks/v2-social-block/v2-social-block.css b/blocks/v2-social-block/v2-social-block.css index b3f0b6e0..46773046 100644 --- a/blocks/v2-social-block/v2-social-block.css +++ b/blocks/v2-social-block/v2-social-block.css @@ -2,32 +2,29 @@ padding: 40px 16px; } -.v2-social-block-container { - --social-block-padding: 24px 16px; - --social-block-gap: 16px; - --social-block-list-gap: 12px; +.redesign-v2 .section.v2-social-block-container .v2-social-block-wrapper { + padding: 0; } .v2-social-block { + --social-block-padding: 24px 16px; + --social-block-gap: 16px; + --social-block-list-gap: 12px; --social-link-color: var(--c-main-black); --social-text-color: var(--c-main-black); -} -.redesign-v2 .section .v2-social-block-wrapper { padding: var(--social-block-padding); border-radius: 8px; } -.v2-social-block-wrapper--black { +.v2-social-block--black { background-color: var(--c-main-black); -} -.v2-social-block--black { --social-link-color: var(--c-white); --social-text-color: var(--c-grey-2); } -.v2-social-block-wrapper--gray { +.v2-social-block--gray { background-color: var(--c-grey-50); } @@ -67,7 +64,7 @@ } .v2-social-block__button:focus-visible { - outline: 2px solid var(--light-border-focus); + outline: 2px solid var(--border-focus); outline-offset: 1px; } @@ -81,7 +78,7 @@ padding: 40px 32px; } - .v2-social-block-container { + .v2-social-block { --social-block-padding: 32px; } @@ -100,8 +97,8 @@ padding: 48px 0; } - .v2-social-block-container { + .v2-social-block { --social-block-padding: 48px 40px; --social-block-gap: 32px; - } -} \ No newline at end of file + } +} diff --git a/blocks/v2-social-block/v2-social-block.js b/blocks/v2-social-block/v2-social-block.js index 3537ee72..b523ceb4 100644 --- a/blocks/v2-social-block/v2-social-block.js +++ b/blocks/v2-social-block/v2-social-block.js @@ -4,12 +4,6 @@ export default async function decorate(block) { const blockName = 'v2-social-block'; const variantClasses = ['black', 'gray']; - if (block.classList.contains('black')) { - block.parentElement.classList.add('v2-social-block-wrapper--black'); - } else if (block.classList.contains('gray')) { - block.parentElement.classList.add('v2-social-block-wrapper--gray'); - } - variantsClassesToBEM(block.classList, variantClasses, blockName); const headings = block.querySelectorAll('h1, h2, h3, h4, h5, h6'); diff --git a/blocks/v2-static-content-carousel/v2-static-content-carousel.css b/blocks/v2-static-content-carousel/v2-static-content-carousel.css index e00c4dec..f71795c3 100644 --- a/blocks/v2-static-content-carousel/v2-static-content-carousel.css +++ b/blocks/v2-static-content-carousel/v2-static-content-carousel.css @@ -86,7 +86,7 @@ /* stylelint-disable-next-line no-descending-specificity */ .v2-static-content-carousel__button:focus-visible { - outline: 2px solid var(--light-border-focus); + outline: 2px solid var(--border-focus); outline-offset: 1px; } @@ -100,12 +100,12 @@ } .v2-static-content-carousel__button .icon-arrow-left svg, -.v2-static-content-carousel__button .icon-arrow-right svg { +.v2-static-content-carousel__button .icon-arrow-right svg { width: 48px; height: 48px; } -.v2-static-content-carousel__button:disabled .icon-arrow-right svg path, +.v2-static-content-carousel__button:disabled .icon-arrow-right svg path, .v2-static-content-carousel__button:disabled .icon-arrow-left svg path { fill: var(--c-grey-2) } @@ -172,4 +172,4 @@ background: linear-gradient(90deg, rgb(255 255 255 / 0%) 0%, var(--background-gradient) 100%); right: 0; } -} \ No newline at end of file +} diff --git a/blocks/v2-stories-carousel/v2-stories-carousel.css b/blocks/v2-stories-carousel/v2-stories-carousel.css index f0a57053..35725ce5 100644 --- a/blocks/v2-stories-carousel/v2-stories-carousel.css +++ b/blocks/v2-stories-carousel/v2-stories-carousel.css @@ -168,7 +168,7 @@ ul.v2-stories-carousel-meta { } .v2-stories-carousel-arrowcontrols button:focus-visible { - outline: 2px solid var(--light-border-focus); + outline: 2px solid var(--border-focus); outline-offset: 1px; } diff --git a/blocks/v2-truck-lineup/v2-truck-lineup.css b/blocks/v2-truck-lineup/v2-truck-lineup.css index 3162b8ab..096ea65c 100644 --- a/blocks/v2-truck-lineup/v2-truck-lineup.css +++ b/blocks/v2-truck-lineup/v2-truck-lineup.css @@ -199,7 +199,7 @@ ul.v2-truck-lineup__navigation { } .v2-truck-lineup__navigation button:focus-visible { - outline: 2px solid var(--light-border-focus); + outline: 2px solid var(--border-focus); outline-offset: 5px; } @@ -259,7 +259,7 @@ ul.v2-truck-lineup__navigation { } .v2-truck-lineup__arrow-controls button:focus-visible { - outline: 2px solid var(--light-border-focus); + outline: 2px solid var(--border-focus); outline-offset: 1px; } diff --git a/common/modal/modal.css b/common/modal/modal.css index 98a4728a..dd3148ed 100644 --- a/common/modal/modal.css +++ b/common/modal/modal.css @@ -101,7 +101,7 @@ } .modal-top-bar .modal-close-button:focus-visible { - outline: 2px solid var(--light-border-focus); + outline: 2px solid var(--border-focus); outline-offset: 5px; } diff --git a/icons/checkbox.svg b/icons/checkbox.svg new file mode 100644 index 00000000..2b2fa40b --- /dev/null +++ b/icons/checkbox.svg @@ -0,0 +1,3 @@ + + + diff --git a/placeholder.json b/placeholder.json index 6b482db4..8ea82b1d 100644 --- a/placeholder.json +++ b/placeholder.json @@ -166,7 +166,35 @@ { "Key": "Copied", "Text": "Copied!" - }, + }, + { + "Key": "event-notify:first-name", + "Text": "First name" + }, + { + "Key": "event-notify:last-name", + "Text": "Last name" + }, + { + "Key": "event-notify:zip", + "Text": "ZIP" + }, + { + "Key": "event-notify:email", + "Text": "Email" + }, + { + "Key": "event-notify:agreement", + "Text": "I agree to receive email updates from Volvo Trucks North America" + }, + { + "Key": "event-notify:notify", + "Text": "Notify me" + }, + { + "Key": "event-notify:add-event", + "Text": "Add event to calendar" + }, { "Key": "view all", "Text": "View all" diff --git a/styles/styles.css b/styles/styles.css index 661d859c..bd1498b4 100644 --- a/styles/styles.css +++ b/styles/styles.css @@ -6,7 +6,7 @@ */ @font-face { font-family: 'VolvoNovum Fallback'; - src: local("arial"); + src: local('arial'); size-adjust: 102%; ascent-override: 95%; descent-override: normal; @@ -29,7 +29,7 @@ font-weight: 400; ascent-override: 120.58%; descent-override: 23.83%; - line-gap-override: 0.00%; + line-gap-override: 0%; size-adjust: 69.25%; } @@ -40,19 +40,22 @@ src: local('Arial'); ascent-override: 93.75%; descent-override: 6.25%; - line-gap-override: 0.00%; - size-adjust: 100.00%; + line-gap-override: 0%; + size-adjust: 100%; } :root { /* fonts */ - --ff-volvo-novum-medium: 'VolvoNovum-Medium', 'VolvoNovum-Medium Fallback', sans-serif; + --ff-volvo-novum-medium: 'VolvoNovum-Medium', 'VolvoNovum-Medium Fallback', + sans-serif; --ff-volvo-novum: 'VolvoNovum', 'VolvoNovum Fallback', sans-serif; - --ff-volvo-broadprodigital: 'VolvoBroadProDigital', 'VolvoBroadProDigital Fallback', sans-serif; + --ff-volvo-broadprodigital: 'VolvoBroadProDigital', + 'VolvoBroadProDigital Fallback', sans-serif; --ff-fontawesome: 'fontawesome', 'fontawesome Fallback'; --font-family-body: var(--ff-volvo-novum); --font-family-heading: var(--ff-volvo-novum-medium); - --font-family-fixed: 'Roboto Mono', menlo, consolas, 'Liberation Mono', monospace; + --font-family-fixed: 'Roboto Mono', menlo, consolas, 'Liberation Mono', + monospace; /* REDESIGN */ --border-radius: 8px; @@ -141,32 +144,32 @@ --c-black: #000; --c-white: #fff; --c-volvo-blue: #182871; - --c-dark-blue: #202A44; - --c-leaf-1: #C8E691; - --c-leaf-2: #A8D46B; - --c-leaf-3: #8FC54E; - --c-leaf-4: #78B833; - --c-teal-1: #B8DeD8; - --c-teal-2: #8DC9BF; - --c-teal-3: #66B3A6; - --c-teal-4: #50A294; - --c-flow-1: #C3D2D6; - --c-flow-2: #96B0B6; - --c-flow-3: #678C96; + --c-dark-blue: #202a44; + --c-leaf-1: #c8e691; + --c-leaf-2: #a8d46b; + --c-leaf-3: #8fc54e; + --c-leaf-4: #78b833; + --c-teal-1: #b8ded8; + --c-teal-2: #8dc9bf; + --c-teal-3: #66b3a6; + --c-teal-4: #50a294; + --c-flow-1: #c3d2d6; + --c-flow-2: #96b0b6; + --c-flow-3: #678c96; --c-flow-4: #396976; - --c-cta-blue-default: #004FBC; - --c-cta-blue-hover: #2B8EDE; - --c-cta-blue-active: #104E9B; + --c-cta-blue-default: #004fbc; + --c-cta-blue-hover: #2b8ede; + --c-cta-blue-active: #104e9b; --c-cta-blue-visited: #346559; /* Greyscale */ - --c-grey-50: #F7F7F7; - --c-grey-100: #EDEDED; - --c-grey-200: #E1E1E1; - --c-grey-300: #D0D0D0; - --c-grey-400: #A9A9A9; - --c-grey-500: #8D8D8D; - --c-grey-600: #6E6E6E; + --c-grey-50: #f7f7f7; + --c-grey-100: #ededed; + --c-grey-200: #e1e1e1; + --c-grey-300: #d0d0d0; + --c-grey-400: #a9a9a9; + --c-grey-500: #8d8d8d; + --c-grey-600: #6e6e6e; --c-grey-700: #575757; --c-grey-800: #424242; --c-grey-900: #323232; @@ -174,12 +177,16 @@ --c-main-black: #141414; /* Success / error colors */ - --c-error-red: #C4001A; - --c-success-green: #47962D; - --c-warning-yellow: #F7D302; + --c-error-red: #BF2012; + --c-success-green: #1A6C31; + --c-warning-yellow: #FFA000; /* Global colors */ - --light-border-focus: #2B8EDE; + --border-subtle: var(--c-grey-200); + --border-strong: var(--c-grey-400); + --border-hover: #2b8ede; + --border-active: #004FBC; + --border-focus: #2b8ede; /* Motions */ --duration-small: 160ms; @@ -206,10 +213,10 @@ --btn-border-hover: #030333; /* Greyscale */ - --c-grey-1: #E1DFDD; - --c-grey-2: #A7A8A9; - --c-grey-3: #888B8D; - --c-grey-4: #53565A; + --c-grey-1: #e1dfdd; + --c-grey-2: #a7a8a9; + --c-grey-3: #888b8d; + --c-grey-4: #53565a; /* buttons */ --btn-padding: 12px 32px; @@ -230,7 +237,7 @@ --heading-font-size-l: calc(4.8rem * var(--heading-font-size-scale)); --heading-font-size-ml: calc(3.2rem * var(--heading-font-size-scale)); --heading-font-size-m: calc(2.4rem * var(--heading-font-size-scale)); - --heading-font-size-s: calc(2.0rem * var(--heading-font-size-scale)); + --heading-font-size-s: calc(2rem * var(--heading-font-size-scale)); --heading-font-size-xs: calc(1.8rem * var(--heading-font-size-scale)); /* @@ -333,7 +340,7 @@ header.sub-nav-wrapper { header .sub-nav.block { height: var(--sub-nav-height); - background-color: #7F7F7F; + background-color: #7f7f7f; z-index: 1020; left: 0; right: 0; @@ -358,8 +365,16 @@ main.center :where(.block) { text-align: initial; } -h1, h2, h3, -h4, h5, h6 { +main.center :where(.block) { + text-align: initial; +} + +h1, +h2, +h3, +h4, +h5, +h6 { font-family: var(--font-family-heading); font-weight: normal; line-height: 1; @@ -426,7 +441,12 @@ h1#volvo-trucks-magazine { font-size: 60px; } -p, dl, ol, ul, pre, blockquote { +p, +dl, +ol, +ul, +pre, +blockquote { margin-top: 1em; margin-bottom: 1.5em; font-size: var(--body-font-size-xs); @@ -454,13 +474,16 @@ a:hover { color: var(--c-cta-blue-default); } -code, pre, samp { +code, +pre, +samp { font-family: var(--font-family-fixed); font-size: var(--body-font-size-s); } -code, samp { - padding: .125em; +code, +samp { + padding: 0.125em; } pre { @@ -473,7 +496,8 @@ strong { /* buttons */ -a.button:any-link, button { +a.button:any-link, +button { font-family: var(--ff-volvo-novum-medium); box-sizing: border-box; text-decoration: none; @@ -513,18 +537,23 @@ a.button.primary.dark:hover { color: var(--c-white); } -button, input, select, textarea { +button, +input, +select, +textarea { color: inherit; font: inherit; margin: 0; } -button:disabled, button:disabled:hover { +button:disabled, +button:disabled:hover { background-color: var(--overlay-background-color); cursor: unset; } -a.button.primary:hover, button.primary:hover { +a.button.primary:hover, +button.primary:hover { background-color: var(--btn-background-hover); border-color: var(--btn-border-hover); color: var(--text-color); @@ -564,7 +593,7 @@ div:where([role="dialog"]) pre, main pre { background-color: var(--overlay-background-color); padding: 1em; - border-radius: .25em; + border-radius: 0.25em; overflow-x: auto; white-space: pre; } @@ -579,13 +608,13 @@ main blockquote { div:where([role="dialog"]) blockquote p::before, main blockquote p::before { - content: "“"; + content: '“'; line-height: 0; } div:where([role="dialog"]) blockquote p::after, main blockquote p::after { - content: "”"; + content: '”'; line-height: 0; } @@ -600,7 +629,7 @@ div:where([role="dialog"]) img, main img { max-width: 100%; height: auto; - vertical-align: middle + vertical-align: middle; } div:where([role="dialog"]) p img, @@ -622,7 +651,7 @@ main p img { .redesign-v2 a.button:focus-visible, .redesign-v2 button:focus-visible { - outline: 2px solid var(--light-border-focus); + outline: 2px solid var(--border-focus); outline-offset: 2px; } @@ -694,7 +723,8 @@ main .section.highlight { background-color: var(--highlight-background-color); } -body.disable-scroll, body.disable-scroll main { +body.disable-scroll, +body.disable-scroll main { overflow: hidden; } @@ -843,28 +873,28 @@ a.button.text-link-with-video::after { /* pagination */ .pager .pagination ol li .last::before { font-family: var(--ff-fontawesome); - content: "\f051"; + content: '\f051'; font-size: 12px; text-decoration: none; } .pager .pagination ol li .first::before { font-family: var(--ff-fontawesome); - content: "\f048"; + content: '\f048'; font-size: 12px; text-decoration: none; } .pager .pagination ol li .next::before { font-family: var(--ff-fontawesome); - content: "\f054"; + content: '\f054'; font-size: 12px; text-decoration: none; } .pager .pagination ol li .prev::before { font-family: var(--ff-fontawesome); - content: "\f053"; + content: '\f053'; font-size: 12px; text-decoration: none; } @@ -1044,7 +1074,12 @@ main.blue-contract .section.section-with-title p { padding: 0; } -.redesign-v2 body, .redesign-v2 dl, .redesign-v2 ol, .redesign-v2 ul, .redesign-v2 pre, .redesign-v2 blockquote { +.redesign-v2 body, +.redesign-v2 dl, +.redesign-v2 ol, +.redesign-v2 ul, +.redesign-v2 pre, +.redesign-v2 blockquote { font-size: var(--f-body-font-size); line-height: var(--f-body-line-height); letter-spacing: var(--f-body-letter-spacing); @@ -1066,7 +1101,8 @@ main.blue-contract .section.section-with-title p { } .redesign-v2 .section:first-child, -.section:not(.section--black-background, .section--gray-background) + .section:not(.section--black-background, .section--gray-background) { +.section:not(.section--black-background, .section--gray-background) + + .section:not(.section--black-background, .section--gray-background) { padding-top: 0; } @@ -1198,6 +1234,7 @@ main.blue-contract .section.section-with-title p { .redesign-v2 button.secondary { border-color: var(--c-main-black); color: var(--c-main-black); + background-color: transparent; } .redesign-v2 a.button.secondary:hover, @@ -1301,7 +1338,7 @@ main.blue-contract .section.section-with-title p { .redesign-v2 .section--black-background button.marketing-cta, .redesign-v2 a.button.marketing-cta.dark, .redesign-v2 button.marketing-cta.dark { - background-color: #44A1FF; + background-color: #44a1ff; color: var(--c-main-black); } @@ -1309,14 +1346,14 @@ main.blue-contract .section.section-with-title p { .redesign-v2 .section--black-background button.marketing-cta:hover, .redesign-v2 a.button.marketing-cta.dark:hover, .redesign-v2 button.marketing-cta.dark:hover { - background-color: #76BAFF; + background-color: #76baff; } .redesign-v2 .section--black-background a.button.marketing-cta:active, .redesign-v2 .section--black-background button.marketing-cta:active, .redesign-v2 a.button.marketing-cta.dark:active, .redesign-v2 button.marketing-cta.dark:active { - background-color: #1F78D1; + background-color: #1f78d1; } .redesign-v2 :is(h1, h2, h3, h4, h5, h6) a:any-link::after, @@ -1420,6 +1457,65 @@ main.blue-contract .section.section-with-title p { border-color: var(--c-grey-2); } +.redesign-v2 .checkbox-with-label { + position: relative; +} + +.redesign-v2 .checkbox-with-label input[type='checkbox'] { + left: 3px; + top: 3px; + width: 18px; + height: 18px; + position: absolute; + opacity: 1; + margin: 0; + z-index: -1; +} + +.redesign-v2 .checkbox-with-label input[type='checkbox'] + label { + display: flex; + gap: 10px; + user-select: none; + font-size: var(--f-button-font-size); + letter-spacing: var(--f-button-letter-spacing); + color: var(--text-color); + font-family: var(--font-family-body); + line-height: 100%; + margin: 0; + align-items: center; + + --checkbox-margin: 3px; + --checkbox-size: 18px; +} + +.redesign-v2 .checkbox-with-label input[type='checkbox'] + label::before { + content: ''; + display: inline-block; + width: var(--checkbox-size); + min-width: var(--checkbox-size); + height: var(--checkbox-size); + min-height: var(--checkbox-size); + border: 2px solid var(--border-strong); + border-radius: 2px; + margin: var(--checkbox-margin); + align-self: flex-start; +} + +.redesign-v2 .checkbox-with-label input[type='checkbox']:checked + label::before { + border-color: transparent; +} + +.redesign-v2 .checkbox-with-label input[type='checkbox']:checked + label { + background: url('/icons/checkbox.svg') no-repeat; + background-position-x: var(--checkbox-margin); + background-position-y: var(--checkbox-margin); +} + +.redesign-v2 .checkbox-with-label input[type='checkbox']:focus-visible + label::before { + outline: 2px solid var(--border-focus); + outline-offset: 1px; +} + .redesign-v2 .pretitle { color: var(--text-color); font-feature-settings: 'clig' off, 'liga' off;