diff --git a/blocks/carousel/carousel.css b/blocks/carousel/carousel.css
new file mode 100644
index 0000000..af5faed
--- /dev/null
+++ b/blocks/carousel/carousel.css
@@ -0,0 +1,227 @@
+.section.carousel-container {
+ padding: 0;
+}
+
+.carousel .carousel-slides-container {
+ position: relative;
+}
+
+.carousel .carousel-slides,
+.carousel .carousel-slide-indicators {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.carousel .carousel-slides {
+ display: flex;
+ scroll-behavior: smooth;
+ scroll-snap-type: x mandatory;
+ overflow: scroll clip;
+}
+
+.carousel .carousel-slides::-webkit-scrollbar {
+ display: none;
+}
+
+.carousel .carousel-slide {
+ flex: 0 0 100%;
+ scroll-snap-align: start;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: center;
+ position: relative;
+ width: 100%;
+ min-height: 1015px;
+}
+
+.carousel .carousel-slide:has(.carousel-slide-content[data-align="center"]) {
+ align-items: center;
+}
+
+.carousel .carousel-slide:has(.carousel-slide-content[data-align="right"]) {
+ align-items: flex-end;
+}
+
+.carousel .carousel-slide .carousel-slide-image picture {
+ position: absolute;
+ inset: 0;
+}
+
+.carousel .carousel-slide .carousel-slide-image picture > img {
+ height: 100%;
+ width: 100%;
+ object-fit: cover;
+}
+
+.carousel .carousel-slide .carousel-slide-content {
+ z-index: 1;
+ padding: 1rem;
+ margin: 1.5rem 3rem;
+ color: white;
+ background-color: none;
+ position: relative;
+ width: var(--slide-content-width, auto);
+}
+
+.carousel .carousel-slide .carousel-slide-content .button {
+ display: flex;
+ max-width: 260px;
+ align-items: center;
+ max-height: 60px;
+ position: relative;
+ border: 0;
+ height: 6rem;
+ width: 100%;
+ font-family: Calibre, Helvetica, Tahoma, Arial, sans-serif;
+ cursor: pointer;
+ appearance: none;
+ border-radius: .4rem;
+ transition: all .2s ease-in-out;
+ background: #80ba27;
+ color: #fff;
+ letter-spacing: -.02rem;
+ box-shadow: 0 .2rem .4rem 0 rgba(0 0 0 / 5%);
+ font-size: 18px;
+ font-weight: normal;
+}
+
+.carousel .carousel-slide-image::after {
+ width: 100vw;
+ height: 100vh;
+ display: block;
+ position: absolute;
+ top:0;
+ left: 0;
+ background-color: rgba(0 0 0 /30%);
+ content: " ";
+}
+
+.carousel .carousel-slide-indicators {
+ display: flex;
+ justify-content: center;
+ gap: 0.5rem;
+}
+
+.carousel .carousel-slide-indicator button {
+ width: 1rem;
+ height: 1rem;
+ padding: 0;
+ border-radius: 1rem;
+ background-color: rgba(0 0 0 / 25%);
+}
+
+.carousel .carousel-slide-indicator button:disabled,
+.carousel .carousel-slide-indicator button:hover,
+.carousel .carousel-slide-indicator button:focus-visible {
+ background-color: rgba(0 0 0 / 80%);
+}
+
+.carousel .carousel-slide-indicator span,
+.carousel .carousel-navigation-buttons span {
+ border: 0;
+ clip: rect(0 0 0 0);
+ clip-path: inset(50%);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+ white-space: nowrap;
+}
+
+.carousel .carousel-navigation-buttons {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ left: 0.5rem;
+ right: 0.5rem;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 20px;
+ margin-right: 5rem;
+ z-index: 1;
+}
+
+/* stylelint-disable-next-line no-descending-specificity */
+.carousel .carousel-navigation-buttons button {
+ border-radius: 8px;
+ margin: 0;
+ padding: 0;
+ width: 2rem;
+ height: 2rem;
+ position: relative;
+ background-color: transparent;
+}
+
+.carousel .carousel-navigation-buttons button:hover,
+.carousel .carousel-navigation-buttons button:focus-visible {
+ background-color: transparent;
+}
+
+.carousel .carousel-navigation-buttons button::after {
+ display: block;
+ content: "";
+ border: 3px white solid;
+ border-bottom: 0;
+ border-left: 0;
+ height: 0.75rem;
+ width: 0.75rem;
+ position: absolute;
+ top: 50%;
+ left: calc(50% + 3px);
+ transform: translate(-50%, -50%) rotate(-135deg);
+}
+
+.carousel .carousel-navigation-buttons button.slide-next::after {
+ transform: translate(-50%, -50%) rotate(45deg);
+ left: calc(50% - 3px);
+}
+
+@media (width >= 600px) {
+ .carousel .carousel-navigation-buttons {
+ left: 1rem;
+ right: 1rem;
+ }
+
+ .carousel .carousel-navigation-buttons button {
+ width: 3rem;
+ height: 3rem;
+ }
+
+ .carousel .carousel-navigation-buttons button::after {
+ width: 1rem;
+ height: 1rem;
+ }
+
+ .carousel .carousel-slide .carousel-slide-content {
+ --slide-content-width: 50%;
+
+ margin: 2.5rem 5rem;
+ }
+
+ .carousel .carousel-slide .carousel-slide-content h3 {
+ color: #fff;
+ }
+
+ .carousel .carousel-slide .carousel-slide-content[data-align="justify"] {
+ --slide-content-width: auto;
+ }
+}
+
+
+.carousel-container .carousel-wrapper {
+ max-width: 100%;
+ height: calc(100vh - 64px);
+ min-height: calc(100vh - 64px);
+}
+
+@media (width >= 900px) {
+ .carousel-container .carousel-wrapper {
+ max-width: 100%;
+ min-height: 1015px;
+ }
+}
diff --git a/blocks/carousel/carousel.js b/blocks/carousel/carousel.js
new file mode 100644
index 0000000..2b1ae16
--- /dev/null
+++ b/blocks/carousel/carousel.js
@@ -0,0 +1,150 @@
+import { fetchPlaceholders } from '../../scripts/aem.js';
+
+function updateActiveSlide(slide) {
+ const block = slide.closest('.carousel');
+ const slideIndex = parseInt(slide.dataset.slideIndex, 10);
+ block.dataset.activeSlide = slideIndex;
+
+ const slides = block.querySelectorAll('.carousel-slide');
+
+ slides.forEach((aSlide, idx) => {
+ aSlide.setAttribute('aria-hidden', idx !== slideIndex);
+ aSlide.querySelectorAll('a').forEach((link) => {
+ if (idx !== slideIndex) {
+ link.setAttribute('tabindex', '-1');
+ } else {
+ link.removeAttribute('tabindex');
+ }
+ });
+ });
+
+ const indicators = block.querySelectorAll('.carousel-slide-indicator');
+ indicators.forEach((indicator, idx) => {
+ if (idx !== slideIndex) {
+ indicator.querySelector('button').removeAttribute('disabled');
+ } else {
+ indicator.querySelector('button').setAttribute('disabled', 'true');
+ }
+ });
+}
+
+function showSlide(block, slideIndex = 0) {
+ const slides = block.querySelectorAll('.carousel-slide');
+ let realSlideIndex = slideIndex < 0 ? slides.length - 1 : slideIndex;
+ if (slideIndex >= slides.length) realSlideIndex = 0;
+ const activeSlide = slides[realSlideIndex];
+
+ activeSlide.querySelectorAll('a').forEach((link) => link.removeAttribute('tabindex'));
+ block.querySelector('.carousel-slides').scrollTo({
+ top: 0,
+ left: activeSlide.offsetLeft,
+ behavior: 'smooth',
+ });
+}
+
+function bindEvents(block) {
+ const slideIndicators = block.querySelector('.carousel-slide-indicators');
+ if (!slideIndicators) return;
+
+ slideIndicators.querySelectorAll('button').forEach((button) => {
+ button.addEventListener('click', (e) => {
+ const slideIndicator = e.currentTarget.parentElement;
+ showSlide(block, parseInt(slideIndicator.dataset.targetSlide, 10));
+ });
+ });
+
+ block.querySelector('.slide-prev').addEventListener('click', () => {
+ showSlide(block, parseInt(block.dataset.activeSlide, 10) - 1);
+ });
+ block.querySelector('.slide-next').addEventListener('click', () => {
+ showSlide(block, parseInt(block.dataset.activeSlide, 10) + 1);
+ });
+
+ const slideObserver = new IntersectionObserver((entries) => {
+ entries.forEach((entry) => {
+ if (entry.isIntersecting) updateActiveSlide(entry.target);
+ });
+ }, { threshold: 0.5 });
+ block.querySelectorAll('.carousel-slide').forEach((slide) => {
+ slideObserver.observe(slide);
+ });
+}
+
+function createSlide(row, slideIndex, carouselId) {
+ const slide = document.createElement('li');
+ slide.dataset.slideIndex = slideIndex;
+ slide.setAttribute('id', `carousel-${carouselId}-slide-${slideIndex}`);
+ slide.classList.add('carousel-slide');
+
+ row.querySelectorAll(':scope > div').forEach((column, colIdx) => {
+ column.classList.add(`carousel-slide-${colIdx === 0 ? 'image' : 'content'}`);
+ slide.append(column);
+ });
+
+ const labeledBy = slide.querySelector('h1, h2, h3, h4, h5, h6');
+ if (labeledBy) {
+ slide.setAttribute('aria-labelledby', labeledBy.getAttribute('id'));
+ }
+
+ return slide;
+}
+
+let carouselId = 0;
+export default async function decorate(block) {
+ carouselId += 1;
+ block.setAttribute('id', `carousel-${carouselId}`);
+ const rows = block.querySelectorAll(':scope > div');
+ const isSingleSlide = rows.length < 2;
+
+ const placeholders = await fetchPlaceholders();
+
+ block.setAttribute('role', 'region');
+ block.setAttribute('aria-roledescription', placeholders.carousel || 'Carousel');
+
+ const container = document.createElement('div');
+ container.classList.add('carousel-slides-container');
+
+ const slidesWrapper = document.createElement('ul');
+ slidesWrapper.classList.add('carousel-slides');
+ block.prepend(slidesWrapper);
+
+ let slideIndicators;
+ if (!isSingleSlide) {
+ const slideIndicatorsNav = document.createElement('nav');
+ slideIndicatorsNav.setAttribute('aria-label', placeholders.carouselSlideControls || 'Carousel Slide Controls');
+ slideIndicators = document.createElement('ol');
+ slideIndicators.classList.add('carousel-slide-indicators');
+ slideIndicatorsNav.append(slideIndicators);
+ block.append(slideIndicatorsNav);
+
+ const slideNavButtons = document.createElement('div');
+ slideNavButtons.classList.add('carousel-navigation-buttons');
+ slideNavButtons.innerHTML = `
+
+
+ `;
+
+ container.append(slideNavButtons);
+ }
+
+ rows.forEach((row, idx) => {
+ const slide = createSlide(row, idx, carouselId);
+ slidesWrapper.append(slide);
+
+ if (slideIndicators) {
+ const indicator = document.createElement('li');
+ indicator.classList.add('carousel-slide-indicator');
+ indicator.dataset.targetSlide = idx;
+ indicator.innerHTML = ``;
+ slideIndicators.append(indicator);
+ }
+ row.remove();
+ });
+
+ container.append(slidesWrapper);
+ block.prepend(container);
+
+ if (!isSingleSlide) {
+ bindEvents(block);
+ }
+}
diff --git a/blocks/logo/logo.css b/blocks/logo/logo.css
new file mode 100644
index 0000000..a363948
--- /dev/null
+++ b/blocks/logo/logo.css
@@ -0,0 +1,3 @@
+.logo {
+ display: block;
+}
\ No newline at end of file
diff --git a/favicon.ico b/favicon.ico
index 96ab42c..2ef03c7 100644
Binary files a/favicon.ico and b/favicon.ico differ
diff --git a/icons/arrow-right.svg b/icons/arrow-right.svg
new file mode 100644
index 0000000..970c1c7
--- /dev/null
+++ b/icons/arrow-right.svg
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/styles/styles.css b/styles/styles.css
index b4f62ee..509d4dd 100644
--- a/styles/styles.css
+++ b/styles/styles.css
@@ -13,7 +13,7 @@
:root {
/* colors */
--link-color: #80ba27;
- --link-hover-color: #80ba27;
+ --link-hover-color: #000;
--background-color: white;
--light-color: #eee;
--dark-color: #ccc;
@@ -167,7 +167,7 @@ a.button:hover,
a.button:focus,
button:hover,
button:focus {
- background-color: var(--link-hover-color);
+ background-color: var(--link-color);
cursor: pointer;
}