diff --git a/.github/workflows/test.yml-template b/.github/workflows/test.yml-template new file mode 100644 index 000000000..8b5743ecb --- /dev/null +++ b/.github/workflows/test.yml-template @@ -0,0 +1,29 @@ +name: Test + +on: + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [20.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm test + - name: Upload HTML report(backstop data) + if: ${{ always() }} + uses: actions/upload-artifact@v2 + with: + name: report + path: backstop_data diff --git a/README.md b/README.md index 302783df5..36db04b83 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # KateVR landing page (HARD) -**⚠️ Attention: this is a hard landing page for development. We highly recommend choosing this landing page only if you didn't have a lot of troubles with previous homework tasks and if you sent all homework in time (didn't miss deadlines).** +**⚠️ Attention: this is a hard landing page for development. We highly recommend choosing this landing page only if you didn't have a lot of troubles with previous homework tasks and if you sent all homework in time (didn't miss deadlines).** Implement landing page according to [Figma design](https://www.figma.com/file/Blpg4iapsI7fRqJeSp6DvK/KatVR?node-id=1%3A370) - Use BEM and SCSS @@ -25,7 +25,7 @@ Implement landing page according to [Figma design](https://www.figma.com/file/Bl 11. `git push origin develop` - to send you code for PR. 12. Create a Pull Request (PR) from your branch `develop` to branch `master` of original repo. 13. Replace `` with your Github username in the - [DEMO LINK](https://.github.io/layout_KateVR/). + [DEMO LINK](https://AngelaStrechen.github.io/layout_KateVR/). 14. Copy `DEMO LINK` to the PR description. > To update you PR repeat steps 7-11. diff --git a/index.html b/index.html index d339e6856..87ee8ceca 100644 --- a/index.html +++ b/index.html @@ -6,14 +6,2383 @@ name="viewport" content="width=device-width, initial-scale=1.0" /> - Title + KatVR + + + + - -

Hello Mate Academy

- + +
+
+
+
+ +
+ + + + +
+
+ En +
+
+ Ua +
+
+ Pl +
+
+ Fr +
+ + +
+
+
+ + + + +
+ +
+
+  +
+ +
+

+ THE NEW START OF +
+ VR LOCOMOTION +

+ +

+ Discover the most comprehensive VR Locomotion system, and unlock + infinite motion in any games on any platforms! +

+
1200$
+ + +
+
+ +
+ + + + +
+ + + + +
+ + + + + +
+
+
+
+
+ +
+ +
+
+

+ More than + Gaming! +

+ +

+ This also made for people who are interested in... +

+ +
+ +
+ Icon + +

Education

+ +

+ Create aducational simulations, trainings and much more with + unlimited virtual space and minimum physical space +

+
+ + +
+ Icon + +

Real estate

+ +

+ Desighn architectural projects in a deeply realistic environment + allowing visitors to freely walk around, and feel their vibe +

+
+ + +
+ Icon + +

Fitness

+ +

+ Combine business with pleasure, and discover countless ways to + stay fit while playing your favorite VR Games! +

+
+ + +
+ Icon + +

Social interactions

+ +

+ Hang out with your friends in the virtual world when you can’t + meet space requirements +

+
+
+
+
+ + +
+
+
+ +

+ About + + product + +

+
+ 1 + + /5 +
+
+
+ Product +
+ +
+ + + + + +
+ +
+ + + + +
+ + + + + + + +
+
+
+ + +
+ +

+ + About + + + product + +

+ +

+ KAT loco is a foot-based VR locomotion system that gives + complete physical control over lower-body actions, allowing you + to freely walk, run, and carry out just any other movement in + virtual reality. +

+ + +
+
+ + +
+
+

+ + Hello, +
+
+ + Nice to meet + + + you! + +

+ +

+ KAT VR is an independent company dedicated to the research, + development, and sales of VR Locomotion products and solutions. + Founded in 2013, we have quickly grown to become one of the + world’s leading professional suppliers of VR games’ & + simulations’ equipment +

+
+ +
+ About + + About + + About + + About + + About + + About + + About +
+
+
+
+ + +
+
+

+ Tech + Specs +

+ +
+ +
+ Product technical specifications + +  + +  + +  + +  + +
+
+

Sensor

+ +

Weight: 35g/1.23oz each

+

Dimension: 50mm/1.97in

+

24mm/0.94in

+

Light: LED lights

+
+ +
+

Batteries

+ +

+ Type: Lithium-ion polymer batteries +

+

Capacity: 370mAh

+

+ Battery life: 10h of continuous use 150 hours on stand by +

+

+ Charging: Fast charging - 1 hour +

+

+ Charging voltage and current: 5V = 0.5A +

+
+ +
+

Connection

+ +

Wireless: Bluetooth 4.2

+

Signal range: 5m

+

Receiver: USB 2.0 and above

+
+
+ + +
+ + +
+

Sensor

+ +

Weight: 35g/1.23oz each

+

Dimension: 50mm/1.97in

+

24mm/0.94in

+

Light: LED lights

+
+
+ + +
+ + +
+

Batteries

+ +

+ Type: Lithium-ion polymer batteries +

+

Capacity: 370mAh

+

+ Battery life: 10h of continuous use 150 hours on stand by +

+

+ Charging: Fast charging - 1 hour +

+

+ Charging voltage and current: 5V = 0.5A +

+
+
+ + +
+ + +
+

Connection

+ +

Wireless: Bluetooth 4.2

+

Signal range: 5m

+

Receiver: USB 2.0 and above

+
+
+
+
+
+
+ + +
+
+

+ WHY + KAT LOCO? +

+ +
+ +
+ Icon + +

universally compatible

+ +

+ KAT Loco offers universal compatibility across all major VR + headsets and platforms allowing you to play any VR game with + support for Free Locomotion +

+
+ + +
+ Icon + +

vr/ps control panel

+ +

+ Our Multifunctional Software allows for quick access to KAT + Loco’s control panel both from a computer desktop, and directly + from your VR headset. +

+
+ + +
+ Icon + +

wireless sensors

+ +

+ What makes it even more advanced, KAT Loco is entirely wireless, + and comes with a complete system of algorithms, super durable + batteries and more! +

+
+
+ + +
+
+
+ + + + +
+
+
+ + + +
+
+ +
+ + + + + + +
+ +
+
+ +
+
+ + + + +
+ +
+
+ CAT VR +
+ +
+
+
+

Quantity

+ +
+ +
+
+ +
+

Price

+ +
+ 1200$ +
+
+
+
+
+
+
+ + + + + + + + +
+ + +
+ +
+
+ +
+ + +
+ +
+
+ +
+ +
+ +
+ +
+
+ + +
+
+ + + + + +
+
+
+
+ + +
+ + + + + + + +
+
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+
+ + +
+
+ + + + + +
+
+

+ + Thank you for + + + your + + + order! + +

+ +

+ Your order has been placed and is being processed. We will send + you a confirmation email shortly. +

+ + +
+
+
+
+
+ + + + + +
+
+ + + +
+
+ + +
+
+ +
+ + +

+ How can we + help + you? +

+ +

+ Welcome to our help center. Our goal is to make the process of getting + acquainted and purchase as easy and pleasant as possible. Need help + with your KAT VR loco product? Many product questions can be resolved + by reviewing our Product Support + + FAQs + + . + +
+ Please also feel free to + + Contact Us + + directly should you need anything further. We’re happy to help. +

+ + +
+
+ + +
+
+ +
+ + +

+ Frequently asked + Questions +

+ +
+
+ + +
+

+ Despite being approached from many different angles, all + traditional VR Locomotion systems including roomscale, + teleportation, and free locomotion failed to provide an optimal + solution capable of integrating high immersion with convenience. + KAT loco does all of that without repeating their flaws. Our + system offers a complete and versatile solution for an + affordable price what makes it a perfect choice for home-use. It + is also 100% user friendly, wireless, universally compatible, + and more! It even offers decoupled head and body directions! +

+
+ Last updated: Wed, June 12 2019 7:07 PM UTC +03:00 +
+
+
+ +
+ + +
+

+ Despite being approached from many different angles, all + traditional VR Locomotion systems including roomscale, + teleportation, and free locomotion failed to provide an optimal + solution capable of integrating high immersion with convenience. + KAT loco does all of that without repeating their flaws. Our + system offers a complete and versatile solution for an + affordable price what makes it a perfect choice for home-use. It + is also 100% user friendly, wireless, universally compatible, + and more! It even offers decoupled head and body directions! +

+
+ Last updated: Wed, June 12 2019 7:07 PM UTC +03:00 +
+
+
+ +
+ + +
+

+ Despite being approached from many different angles, all + traditional VR Locomotion systems including roomscale, + teleportation, and free locomotion failed to provide an optimal + solution capable of integrating high immersion with convenience. + KAT loco does all of that without repeating their flaws. Our + system offers a complete and versatile solution for an + affordable price what makes it a perfect choice for home-use. It + is also 100% user friendly, wireless, universally compatible, + and more! It even offers decoupled head and body directions! +

+
+ Last updated: Wed, June 12 2019 7:07 PM UTC +03:00 +
+
+
+ +
+ + +
+

+ Despite being approached from many different angles, all + traditional VR Locomotion systems including roomscale, + teleportation, and free locomotion failed to provide an optimal + solution capable of integrating high immersion with convenience. + KAT loco does all of that without repeating their flaws. Our + system offers a complete and versatile solution for an + affordable price what makes it a perfect choice for home-use. It + is also 100% user friendly, wireless, universally compatible, + and more! It even offers decoupled head and body directions! +

+
+ Last updated: Wed, June 12 2019 7:07 PM UTC +03:00 +
+
+
+
+ +
+ More + + + +
+
+
+ + +
+ +
+ + + diff --git a/package-lock.json b/package-lock.json index 87fcefd81..e0b0d490d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@linthtml/linthtml": "^0.9.6", "@mate-academy/bemlint": "latest", "@mate-academy/linthtml-config": "latest", - "@mate-academy/scripts": "^2.1.2", + "@mate-academy/scripts": "^2.1.3", "@mate-academy/stylelint-config": "latest", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", @@ -1510,10 +1510,11 @@ "dev": true }, "node_modules/@mate-academy/scripts": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-2.1.2.tgz", - "integrity": "sha512-gUXFdqqOfYzF9R3RSx2pCa5GLdOkxB9bFbF+dpUpzucdgGAANqOGdqpmNnMj+e3xA9YHraUWq3xo9cwe5vD9pQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-2.1.3.tgz", + "integrity": "sha512-a07wHTj/1QUK2Aac5zHad+sGw4rIvcNl5lJmJpAD7OxeSbnCdyI6RXUHwXhjF5MaVo9YHrJ0xVahyERS2IIyBQ==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/rest": "^17.11.2", "@types/get-port": "^4.2.0", diff --git a/package.json b/package.json index 7149ff15d..754178035 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@linthtml/linthtml": "^0.9.6", "@mate-academy/bemlint": "latest", "@mate-academy/linthtml-config": "latest", - "@mate-academy/scripts": "^2.1.2", + "@mate-academy/scripts": "^2.1.3", "@mate-academy/stylelint-config": "latest", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", diff --git a/src/images/about-us/about-us.svg b/src/images/about-us/about-us.svg new file mode 100644 index 000000000..603db1987 --- /dev/null +++ b/src/images/about-us/about-us.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/images/about-us/about-us_2.svg b/src/images/about-us/about-us_2.svg new file mode 100644 index 000000000..c25312550 --- /dev/null +++ b/src/images/about-us/about-us_2.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/images/about-us/about-us_3.svg b/src/images/about-us/about-us_3.svg new file mode 100644 index 000000000..475d657fc --- /dev/null +++ b/src/images/about-us/about-us_3.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/images/about-us/about-us_4.svg b/src/images/about-us/about-us_4.svg new file mode 100644 index 000000000..d5dc2c566 --- /dev/null +++ b/src/images/about-us/about-us_4.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/images/about-us/about-us_5.svg b/src/images/about-us/about-us_5.svg new file mode 100644 index 000000000..50f733f4d --- /dev/null +++ b/src/images/about-us/about-us_5.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/images/about-us/about-us_6.svg b/src/images/about-us/about-us_6.svg new file mode 100644 index 000000000..fcf9d6575 --- /dev/null +++ b/src/images/about-us/about-us_6.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/images/about-us/about-us_7.svg b/src/images/about-us/about-us_7.svg new file mode 100644 index 000000000..4e12b51a9 --- /dev/null +++ b/src/images/about-us/about-us_7.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/images/about-us/image-2.jpg b/src/images/about-us/image-2.jpg new file mode 100644 index 000000000..8ed1999c5 Binary files /dev/null and b/src/images/about-us/image-2.jpg differ diff --git a/src/images/about-us/image-3.jpg b/src/images/about-us/image-3.jpg new file mode 100644 index 000000000..8ed1999c5 Binary files /dev/null and b/src/images/about-us/image-3.jpg differ diff --git a/src/images/about-us/image-4.jpg b/src/images/about-us/image-4.jpg new file mode 100644 index 000000000..8ed1999c5 Binary files /dev/null and b/src/images/about-us/image-4.jpg differ diff --git a/src/images/about-us/image-5.jpg b/src/images/about-us/image-5.jpg new file mode 100644 index 000000000..8ed1999c5 Binary files /dev/null and b/src/images/about-us/image-5.jpg differ diff --git a/src/images/about-us/image.jpg b/src/images/about-us/image.jpg new file mode 100644 index 000000000..8ed1999c5 Binary files /dev/null and b/src/images/about-us/image.jpg differ diff --git a/src/images/checkout-product/checkout-product.png b/src/images/checkout-product/checkout-product.png new file mode 100644 index 000000000..d40c9f192 Binary files /dev/null and b/src/images/checkout-product/checkout-product.png differ diff --git a/src/images/checkout-product/visa.jpg b/src/images/checkout-product/visa.jpg new file mode 100644 index 000000000..a155b1ce4 Binary files /dev/null and b/src/images/checkout-product/visa.jpg differ diff --git a/src/images/header-images/image-desktop.png b/src/images/header-images/image-desktop.png new file mode 100644 index 000000000..d7ed3a47f Binary files /dev/null and b/src/images/header-images/image-desktop.png differ diff --git a/src/images/header-images/image-mobile.png b/src/images/header-images/image-mobile.png new file mode 100644 index 000000000..968dfec27 Binary files /dev/null and b/src/images/header-images/image-mobile.png differ diff --git a/src/images/header-images/image-tablet.png b/src/images/header-images/image-tablet.png new file mode 100644 index 000000000..fc593b224 Binary files /dev/null and b/src/images/header-images/image-tablet.png differ diff --git a/src/images/header-images/image-xxl.png b/src/images/header-images/image-xxl.png new file mode 100644 index 000000000..6a54cac2c Binary files /dev/null and b/src/images/header-images/image-xxl.png differ diff --git a/src/images/icons/arrow-down.svg b/src/images/icons/arrow-down.svg new file mode 100644 index 000000000..801d56619 --- /dev/null +++ b/src/images/icons/arrow-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/cat-vr-logo.svg b/src/images/icons/cat-vr-logo.svg new file mode 100644 index 000000000..b3435d9f7 --- /dev/null +++ b/src/images/icons/cat-vr-logo.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/images/icons/facebook.svg b/src/images/icons/facebook.svg new file mode 100644 index 000000000..c5ce92014 --- /dev/null +++ b/src/images/icons/facebook.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/favicon.svg b/src/images/icons/favicon.svg new file mode 100644 index 000000000..68254a1b0 --- /dev/null +++ b/src/images/icons/favicon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/images/icons/instagram.svg b/src/images/icons/instagram.svg new file mode 100644 index 000000000..cd292e387 --- /dev/null +++ b/src/images/icons/instagram.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/threads.svg b/src/images/icons/threads.svg new file mode 100644 index 000000000..2ec597384 --- /dev/null +++ b/src/images/icons/threads.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/youtube.svg b/src/images/icons/youtube.svg new file mode 100644 index 000000000..bdc8d8ce2 --- /dev/null +++ b/src/images/icons/youtube.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/more-than/education.svg b/src/images/more-than/education.svg new file mode 100644 index 000000000..ed2e4f006 --- /dev/null +++ b/src/images/more-than/education.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/images/more-than/fitness.svg b/src/images/more-than/fitness.svg new file mode 100644 index 000000000..2c3c44e84 --- /dev/null +++ b/src/images/more-than/fitness.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/images/more-than/real_estate.svg b/src/images/more-than/real_estate.svg new file mode 100644 index 000000000..68a503781 --- /dev/null +++ b/src/images/more-than/real_estate.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/images/more-than/social_interactions.svg b/src/images/more-than/social_interactions.svg new file mode 100644 index 000000000..81f8ef946 --- /dev/null +++ b/src/images/more-than/social_interactions.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/images/tech-specs/Image.svg b/src/images/tech-specs/Image.svg new file mode 100644 index 000000000..9d5cfd58a --- /dev/null +++ b/src/images/tech-specs/Image.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/images/tech-specs/decor-line.svg b/src/images/tech-specs/decor-line.svg new file mode 100644 index 000000000..2d162854e --- /dev/null +++ b/src/images/tech-specs/decor-line.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/tech-specs/line-1.svg b/src/images/tech-specs/line-1.svg new file mode 100644 index 000000000..dfc56f6dd --- /dev/null +++ b/src/images/tech-specs/line-1.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/images/tech-specs/line-2.svg b/src/images/tech-specs/line-2.svg new file mode 100644 index 000000000..c1533eae7 --- /dev/null +++ b/src/images/tech-specs/line-2.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/images/tech-specs/line-3.svg b/src/images/tech-specs/line-3.svg new file mode 100644 index 000000000..e2961ab51 --- /dev/null +++ b/src/images/tech-specs/line-3.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/images/why-kat-loco/compatible.svg b/src/images/why-kat-loco/compatible.svg new file mode 100644 index 000000000..0d6d9144c --- /dev/null +++ b/src/images/why-kat-loco/compatible.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/images/why-kat-loco/control-panel.svg b/src/images/why-kat-loco/control-panel.svg new file mode 100644 index 000000000..a5798b8d0 --- /dev/null +++ b/src/images/why-kat-loco/control-panel.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/images/why-kat-loco/sensors.svg b/src/images/why-kat-loco/sensors.svg new file mode 100644 index 000000000..67677d440 --- /dev/null +++ b/src/images/why-kat-loco/sensors.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/scripts/checkout.js b/src/scripts/checkout.js new file mode 100644 index 000000000..28d17a475 --- /dev/null +++ b/src/scripts/checkout.js @@ -0,0 +1,250 @@ +'use strict'; + +// ============================ + +// OPEN CHECKOUT + +// ============================ + +const buyButtons = document.querySelectorAll('.buyButton'); + +const checkout = document.getElementById('checkout'); + +if (checkout) { + buyButtons.forEach((button) => { + button.addEventListener('click', () => { + checkout.classList.add('checkout--active'); + + document.body.classList.add('page_body--no-scroll'); + }); + }); +} + +// ============================ + +// PRICE + +// ============================ + +const PRICE = 1200; + +// ============================ +// ELEMENTS +// ============================ + +const steps = document.querySelectorAll('.checkout__step'); +const pages = document.querySelectorAll('.checkout-page'); +const progressBar = document.querySelector('.checkout__progress-bar'); + +const quantity = document.getElementById('quantity'); +const totalPrice = document.getElementById('totalPrice'); + +const orderForm = document.getElementById('orderForm'); +const paymentForm = document.getElementById('paymentForm'); + +const goToPayment = document.getElementById('goToPayment'); +const completeOrder = document.getElementById('completeOrder'); + +const cardNumber = document.getElementById('cardNumber'); +const expiry = document.getElementById('expiry'); +const cvv = document.getElementById('cvv'); + +const STEP_WIDTH = 100; + +// ============================ +// SHOW PAGE +// ============================ + +function showStep(stepName) { + pages.forEach((page) => { + page.classList.toggle( + 'checkout-page--active', + page.dataset.step === stepName, + ); + }); + + steps.forEach((step) => { + step.classList.toggle( + 'checkout__step--active', + step.dataset.step === stepName, + ); + }); + + let index = 0; + + if (stepName === 'pay') { + index = 1; + } + + if (stepName === 'complete') { + index = 2; + } + + if (progressBar) { + progressBar.style.transform = `translateX(${index * 100}%)`; + } +} + +// ============================ +// CLICK ON TABS +// ============================ + +steps.forEach((step) => { + step.addEventListener('click', () => { + const stepName = step.dataset.step; + + if (stepName === 'order') { + showStep('order'); + } + + if (stepName === 'pay') { + if (orderForm.checkValidity()) { + showStep('pay'); + } else { + orderForm.reportValidity(); + } + } + + if (stepName === 'complete') { + if ( + orderForm.checkValidity() && + paymentForm.checkValidity() && + validateCard() + ) { + showStep('complete'); + } else { + paymentForm.reportValidity(); + } + } + }); +}); + +// ============================ +// PRICE +// ============================ + +if (quantity) { + quantity.addEventListener('change', () => { + const count = Number(quantity.value); + + totalPrice.textContent = `$${count * PRICE}`; + }); +} + +// ============================ +// FIRST BUTTON +// ============================ + +goToPayment?.addEventListener('click', () => { + if (orderForm.checkValidity()) { + showStep('pay'); + } else { + orderForm.reportValidity(); + } +}); + +// ============================ +// SECOND BUTTON +// ============================ + +completeOrder?.addEventListener('click', () => { + if (!paymentForm.checkValidity()) { + paymentForm.reportValidity(); + + return; + } + + if (!validateCard()) { + return; + } + + showStep('complete'); +}); + +// ============================ +// CARD FORMAT +// ============================ + +cardNumber?.addEventListener('input', (e) => { + let value = e.target.value.replace(/\D/g, ''); + + value = value.substring(0, 16); + + value = value.replace(/(.{4})/g, '$1 ').trim(); + + e.target.value = value; +}); + +// ============================ +// DATE FORMAT +// ============================ + +expiry?.addEventListener('input', (e) => { + let value = e.target.value.replace(/\D/g, ''); + + if (value.length > 4) { + value = value.substring(0, 4); + } + + if (value.length > 2) { + value = value.substring(0, 2) + '/' + value.substring(2); + } + + e.target.value = value; +}); + +// ============================ +// CVV +// ============================ + +cvv?.addEventListener('input', (e) => { + e.target.value = e.target.value.replace(/\D/g, '').substring(0, 3); +}); + +// ============================ +// CARD VALIDATION +// ============================ + +function validateCard() { + const number = cardNumber.value.replace(/\s/g, ''); + + if (number.length !== 16) { + alert('Card number must contain 16 digits.'); + + return false; + } + + const exp = expiry.value; + + const regex = /^(0[1-9]|1[0-2])\/([0-9]{2})$/; + + if (!regex.test(exp)) { + alert('Invalid expiration date.'); + + return false; + } + + if (cvv.value.length !== 3) { + alert('Invalid CVV.'); + + return false; + } + + return true; +} + +// ============================ +// BACK HOME +// ============================ + +const homeButton = document.querySelector('.checkout-complete button'); + +homeButton?.addEventListener('click', () => { + window.location.href = './index.html'; +}); + +// ============================ +// START +// ============================ + +showStep('order'); diff --git a/src/scripts/main.js b/src/scripts/main.js index ad9a93a7c..1d98d2e3f 100644 --- a/src/scripts/main.js +++ b/src/scripts/main.js @@ -1 +1,547 @@ 'use strict'; + +/* ========================= + VIDEO MODAL +========================= */ + +const playButtons = document.querySelectorAll('.play-button'); +const videoModal = document.querySelector('#videoModal'); +const closeVideo = document.querySelector('#closeVideo'); +const youtubeVideo = document.querySelector('#youtubeVideo'); + +const videoUrl = + 'https://www.youtube.com/embed/YmUjK9dtYoQ?list=PLsguMOzLnA8wG4637ZqY8ydi2gFCjM3ZG'; + +const openVideo = () => { + if (!videoModal || !youtubeVideo) return; + + youtubeVideo.src = videoUrl; + + videoModal.classList.add('is-open'); +}; + +const closeVideoModal = () => { + if (!videoModal || !youtubeVideo) return; + + videoModal.classList.remove('is-open'); + + youtubeVideo.src = ''; +}; + +// працює для всіх .play-button +playButtons.forEach((button) => { + button.addEventListener('click', openVideo); +}); + +closeVideo?.addEventListener('click', closeVideoModal); + +videoModal?.addEventListener('click', (e) => { + if (e.target === videoModal) { + closeVideoModal(); + } +}); + +/* ========================= + FAQ MODAL +========================= */ + +const faqModal = document.querySelector('#faqModal'); + +const openFaq = (e) => { + e?.preventDefault(); + faqModal?.classList.add('is-open'); +}; + +const closeFaq = () => { + faqModal?.classList.remove('is-open'); +}; + +document + .querySelectorAll('[href="#faqModal"]') + .forEach((item) => item.addEventListener('click', openFaq)); + +document.querySelector('#faqClose')?.addEventListener('click', closeFaq); + +faqModal?.addEventListener('click', (e) => { + if (e.target.classList.contains('faq-modal__overlay')) { + closeFaq(); + } +}); + +/* ========================= + HELP MODAL +========================= */ + +const helpModal = document.querySelector('#helpModal'); + +const openHelp = (e) => { + e?.preventDefault(); + helpModal?.classList.add('is-open'); +}; + +const closeHelp = () => { + helpModal?.classList.remove('is-open'); +}; + +document.querySelectorAll('#helpOpen, #helpOpenMobile').forEach((item) => { + item.addEventListener('click', openHelp); +}); + +document.querySelector('#helpClose')?.addEventListener('click', closeHelp); + +helpModal?.addEventListener('click', (e) => { + if (e.target.classList.contains('help-modal__overlay')) { + closeHelp(); + } +}); + +/* ========================= + MOBILE MENU +========================= */ + +const burger = document.querySelector('.header__burger'); +const mobileMenu = document.querySelector('.mobile-menu'); + +burger?.addEventListener('click', () => { + burger.classList.toggle('is-open'); + mobileMenu?.classList.toggle('is-open'); +}); + +// Закриття меню при кліку на посилання + +const mobileLinks = document.querySelectorAll('.header__link--mobile'); + +mobileLinks.forEach((link) => { + link.addEventListener('click', () => { + burger?.classList.remove('is-open'); + + mobileMenu?.classList.remove('is-open'); + }); +}); + +/* ========================= + MORE BUTTON +========================= */ + +const moreButton = document.querySelector('.header__bottom-more'); + +moreButton?.addEventListener('click', () => { + moreButton.classList.toggle('is-active'); +}); + +/* ========================= + HEADER SLIDER +========================= */ + +document.addEventListener('DOMContentLoaded', () => { + const images = [ + './src/images/header-images/image-mobile.png', + './src/images/header-images/image-mobile.png', + './src/images/header-images/image-mobile.png', + ]; + + const image = document.querySelector('.header__image'); + + const prev = document.querySelector('.header-slider__prev'); + const next = document.querySelector('.header-slider__next'); + const progress = document.querySelector('.header-slider__active'); + + if (!image) return; + + let index = 0; + + function render() { + image.src = images[index]; + + progress.style.transform = `translateX(${index * 100}%)`; + } + + next?.addEventListener('click', () => { + index++; + + if (index >= images.length) { + index = 0; + } + + render(); + }); + + prev?.addEventListener('click', () => { + index--; + + if (index < 0) { + index = images.length - 1; + } + + render(); + }); + + render(); +}); + +/* ========================= + FAQ ACCORDION +========================= */ + +document.querySelectorAll('.faq__question').forEach((button) => { + button.addEventListener('click', () => { + button.closest('.faq__item')?.classList.toggle('is-open'); + }); +}); + +/* ========================= + ABOUT PRODUCT SLIDER +========================= */ + +document.addEventListener('DOMContentLoaded', () => { + const section = document.querySelector('.about-product'); + + if (!section) return; + + const images = [ + './src/images/about-us/image.jpg', + './src/images/about-us/image-2.jpg', + './src/images/about-us/image-3.jpg', + './src/images/about-us/image-4.jpg', + './src/images/about-us/image-5.jpg', + ]; + + const image = section.querySelector('.about-product__image'); + + const current = section.querySelector('.about-product__current'); + + const prev = section.querySelector('.slider-nav-button--prev'); + + const next = section.querySelector('.slider-nav-button--next'); + + const progress = section.querySelector('.slider-progress-active'); + + const dots = [...section.querySelectorAll('.about-product__dot')]; + + let index = 0; + + function renderSlider() { + image.src = images[index]; + + current.textContent = index + 1; + + if (progress) { + progress.style.width = `${100 / images.length}%`; + + progress.style.transform = `translateX(${index * 100}%)`; + } + + dots.forEach((dot, i) => { + dot.classList.toggle('is-active', i === index); + }); + } + + next?.addEventListener('click', () => { + index++; + + if (index >= images.length) { + index = 0; + } + + renderSlider(); + }); + + prev?.addEventListener('click', () => { + index--; + + if (index < 0) { + index = images.length - 1; + } + + renderSlider(); + }); + + dots.forEach((dot, i) => { + dot.addEventListener('click', () => { + index = i; + + renderSlider(); + }); + }); + + function checkMode() { + const isMobile = window.innerWidth < 1024; + + const controls = section.querySelector('.slider'); + + if (isMobile) { + controls?.classList.add('is-hidden'); + + dots.forEach((dot) => { + dot.style.display = 'block'; + }); + } else { + controls?.classList.remove('is-hidden'); + + dots.forEach((dot) => { + dot.style.display = 'none'; + }); + } + } + + renderSlider(); + + checkMode(); + + window.addEventListener('resize', checkMode); +}); +/* ========================= + ESC CLOSE +========================= */ + +document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + closeVideoModal(); + closeFaq(); + closeHelp(); + } +}); + +/* ========================= + LANG +========================= */ + +document.addEventListener('DOMContentLoaded', () => { + const lang = document.querySelector('.lang'); + if (!lang) return; + + const btn = lang.querySelector('.lang__btn'); + const dropdown = lang.querySelector('.lang__dropdown'); + const options = Array.from(lang.querySelectorAll('.lang__option')); + const hidden = lang.querySelector('input'); + const indicator = lang.querySelector('.lang__indicator'); + + let current = hidden?.value || 'en'; + + const updateLang = () => { + const activeOption = options.find((opt) => opt.dataset.value === current); + + if (!activeOption) return; + + // кнопка зверху + btn.innerHTML = ` + + ${activeOption.textContent} + + + `; + + // ховаємо вибрану мову з dropdown + options.forEach((opt) => { + opt.classList.toggle('is-active', opt.dataset.value === current); + + opt.style.display = opt.dataset.value === current ? 'none' : 'block'; + }); + + // позиція бігунка напроти вибраної + const visibleOptions = options.filter( + (opt) => opt.dataset.value !== current, + ); + + const index = visibleOptions.indexOf(activeOption); + + if (indicator) { + indicator.style.transform = `translateY(${index * 100}%)`; + } + }; + + const close = () => { + lang.classList.remove('is-open'); + }; + + btn.addEventListener('click', (e) => { + e.stopPropagation(); + + updateLang(); + + lang.classList.toggle('is-open'); + }); + + document.addEventListener('click', close); + + options.forEach((opt) => { + opt.addEventListener('mouseenter', () => { + options.forEach((o) => o.classList.remove('is-hover')); + + opt.classList.add('is-hover'); + }); + + opt.addEventListener('click', (e) => { + e.stopPropagation(); + + current = opt.dataset.value; + + if (hidden) { + hidden.value = current; + } + + options.forEach((o) => o.classList.remove('is-hover')); + + updateLang(); + close(); + }); + }); + + updateLang(); +}); + +/* ========================= + SPEC +========================= */ + +document.addEventListener('DOMContentLoaded', () => { + const points = document.querySelectorAll('.spec-point'); + + points.forEach((point) => { + const btn = point.querySelector('.spec-point__btn'); + + btn.addEventListener('click', () => { + const isOpen = point.classList.contains('is-active'); + + // закриваємо всі відкриті + points.forEach((p) => { + p.classList.remove('is-active'); + p.querySelector('button').setAttribute('aria-expanded', 'false'); + }); + + // відкриваємо тільки натиснутий + if (!isOpen) { + point.classList.add('is-active'); + btn.setAttribute('aria-expanded', 'true'); + } + }); + }); +}); + +/* ========================= + WHY KAT TEXT +========================= */ +const limit = 70; +const mobileBreakpoint = 1024; + +let openedText = null; + +function closeText(text) { + text.innerHTML = ` + ${text.dataset.short}... + `; + + text.querySelector('.more-dots').addEventListener('click', () => { + openText(text); + }); +} + +function openText(text) { + if (openedText && openedText !== text) { + closeText(openedText); + } + + text.textContent = text.dataset.full; + openedText = text; +} + +function initWhyKat() { + const isMobileOrTablet = window.innerWidth < mobileBreakpoint; + + document.querySelectorAll('.why-kat__item-text').forEach((text) => { + const full = text.dataset.full || text.textContent.trim(); + + text.dataset.full = full; + text.dataset.short = full.slice(0, limit); + + if (!isMobileOrTablet) { + text.textContent = full; + return; + } + + if (text !== openedText) { + closeText(text); + } + }); +} + +initWhyKat(); + +window.addEventListener('resize', () => { + openedText = null; + initWhyKat(); +}); + +/* ========================= + FOOTER +========================= */ + +document.querySelectorAll('.footer__field').forEach((field) => { + const input = field.querySelector('.footer__input, .footer__textarea'); + const label = field.querySelector( + '.footer__label:not(.footer__label--error)', + ); + const error = field.querySelector('.footer__label--error'); + + input.addEventListener('blur', () => { + let message = ''; + + if (!input.value.trim()) { + message = `Please, fill your ${input.name || 'message'}`; + } else if (input.type === 'email' && !input.checkValidity()) { + message = 'Incorrect email format'; + } + + if (message) { + label.style.display = 'none'; + error.textContent = message; + error.style.display = 'block'; + + input.classList.add('touched'); + } else { + error.style.display = 'none'; + label.style.display = 'block'; + + input.classList.remove('touched'); + } + }); + + input.addEventListener('input', () => { + error.style.display = 'none'; + label.style.display = 'block'; + }); +}); + +/* ========================= + BUY FIXED +========================= */ + +document.addEventListener('DOMContentLoaded', () => { + const buyFixed = document.querySelector('.buy-fixed'); + const footer = document.querySelector('footer'); // або '.footer' + + if (!buyFixed || !footer) return; + + const observer = new IntersectionObserver(([entry]) => { + if (entry.isIntersecting) { + buyFixed.classList.add('is-hidden'); + } else { + buyFixed.classList.remove('is-hidden'); + } + }); + + observer.observe(footer); +}); + +/* ========================= + SCROLL TO TOP +========================= */ + +const scrollTopButton = document.querySelector('.footer__scroll-top'); + +scrollTopButton?.addEventListener('click', () => { + window.scrollTo({ + top: 0, + behavior: 'smooth', + }); +}); diff --git a/src/styles/_fonts.scss b/src/styles/_fonts.scss deleted file mode 100644 index 619b8c52b..000000000 --- a/src/styles/_fonts.scss +++ /dev/null @@ -1,6 +0,0 @@ -@font-face { - font-family: Roboto, Arial, Helvetica, sans-serif; - src: url('../fonts/FontFont_FF.Mark.Pro.otf') format('otf'); - font-weight: normal; - font-style: normal; -} diff --git a/src/styles/_typography.scss b/src/styles/_typography.scss deleted file mode 100644 index 1837eb46e..000000000 --- a/src/styles/_typography.scss +++ /dev/null @@ -1,3 +0,0 @@ -h1 { - @extend %h1; -} diff --git a/src/styles/_utils.scss b/src/styles/_utils.scss deleted file mode 100644 index 3280c3fe1..000000000 --- a/src/styles/_utils.scss +++ /dev/null @@ -1,3 +0,0 @@ -@import 'utils/vars'; -@import 'utils/mixins'; -@import 'utils/extends'; diff --git a/src/styles/base/_reset.scss b/src/styles/base/_reset.scss new file mode 100644 index 000000000..7638869f4 --- /dev/null +++ b/src/styles/base/_reset.scss @@ -0,0 +1,95 @@ +/* 1. Box sizing */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* 2. Скидання відступів */ +* { + margin: 0; + padding: 0; +} + +/* 3. Базові налаштування html/body */ +html { + scroll-behavior: smooth; +} + +html, +body { + height: 100%; +} + +body { + -webkit-font-smoothing: antialiased; + + &.no-scroll { + overflow: hidden; + } +} + +/* 5. Форми */ +input, +button, +textarea, +select { + font: inherit; +} + +input, +textarea { + outline: none; + + &:-webkit-autofill, + &:-webkit-autofill:hover, + &:-webkit-autofill:focus, + &:-webkit-autofill:active { + -webkit-box-shadow: 0 0 0 1000px transparent inset; + transition: background-color 5000s ease-in-out 0s; + + -webkit-text-fill-color: inherit; + } +} + +/* 6. Кнопки */ +button { + border: none; + background: none; +} + +/* 7. Списки */ +ul, +ol { + list-style: none; +} + +/* 8. Посилання */ +a { + color: inherit; + text-decoration: none; +} + +a, +button, +input[type='submit'], +input[type='button'], +input[type='checkbox'], +input[type='radio'], +label[for] { + cursor: pointer; +} + +select { + padding: 0; + border: none; + + font: inherit; + color: inherit; + + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background: transparent; + outline: none; +} diff --git a/src/styles/base/_typography.scss b/src/styles/base/_typography.scss new file mode 100644 index 000000000..0635a54bc --- /dev/null +++ b/src/styles/base/_typography.scss @@ -0,0 +1,33 @@ +h1 { + @extend %h1; +} + +h2 { + @extend %h2; +} + +h3 { + @extend %h3; +} + +h4 { + @extend %h4; +} + +.title { + text-transform: uppercase; +} + +p { + @extend %p; +} + +.title--white { + font-weight: 900; + color: $white; +} + +.title--accent { + font-weight: 400; + color: $color-accent; +} diff --git a/src/styles/components/_about-product.scss b/src/styles/components/_about-product.scss new file mode 100644 index 000000000..cfffd1724 --- /dev/null +++ b/src/styles/components/_about-product.scss @@ -0,0 +1,266 @@ +.about-product { + background: linear-gradient(to right, #191536, #000); + background-repeat: no-repeat; + background-size: cover; + + &__product-block { + display: flex; + flex-direction: column; + gap: 20px; + + padding-top: 50px; + padding-bottom: 40px; + + @include on-tablet { + @include page-grid; + + gap: 30px; + } + + @include on-small-desktop { + gap: 32px; + padding-top: 100px; + padding-bottom: 91px; + } + + @include on-large-desktop { + padding-top: 147px; + } + } + + &__title { + margin-bottom: 20px; + + @include on-tablet { + margin-bottom: 30px; + } + + &-mobile { + @include on-tablet { + display: none; + } + } + + &-thin { + margin-bottom: 11px; + font-size: 14px; + font-weight: 400; + color: $color-accent; + } + } + + &-ipad { + display: none; + + @include on-tablet { + display: block; + } + } + + &__counter { + display: none; + + @include on-small-desktop { + display: flex; + grid-column: 2/3; + justify-content: end; + } + + @include on-large-desktop { + grid-column: 3/4; + } + } + + &__slider { + @include on-tablet { + grid-column: 1/4; + } + + @include on-small-desktop { + grid-column: 3/8; + } + + @include on-large-desktop { + grid-column: 4/11; + } + } + + &__image-wrap { + overflow: hidden; + width: 280px; + height: 189px; + margin-bottom: 14px; + + @include on-tablet { + width: 340px; + height: 270px; + } + + @include on-small-desktop { + width: 430px; + height: 290px; + } + + @include on-large-desktop { + width: 622px; + height: 290px; + } + } + + &__image { + display: block; + width: 100%; + height: 100%; + object-fit: cover; + } + + &__dots { + display: flex; + gap: 6px; + align-items: center; + justify-content: center; + + margin-bottom: 20px; + + @include on-small-desktop { + display: none; + } + } + + &__dot { + width: 4px; + height: 4px; + padding: 0; + border: none; + border-radius: 50%; + + background: #484848; + + transition: + background-color 0.25s ease, + transform 0.25s ease; + + &.is-active { + transform: scale(1.15); + background: #ababab; + } + } + + &__slider-nav { + display: none; + + @include on-small-desktop { + display: flex; + } + } + + &__content { + @include on-tablet { + grid-column: 4/-1; + } + + @include on-small-desktop { + grid-column: 9/-1; + } + + @include on-large-desktop { + grid-column: 12/-1; + } + } + &__text { + margin-bottom: 15px; + } + + &__bottom { + padding-bottom: 50px; + + @include on-tablet { + @include page-grid; + + padding-top: 91px; + padding-bottom: 100px; + } + + @include on-small-desktop { + padding-top: 83px; + } + + @include on-large-desktop { + padding-top: 75px; + padding-bottom: 156px; + } + } + + &__hello { + @include on-tablet { + grid-column: 1/5; + } + + @include on-small-desktop { + grid-column: 1/6; + } + + @include on-large-desktop { + grid-column: 2/8; + } + } + + &__small-image { + display: none; + + @include on-tablet { + display: flex; + grid-column: 5/-1; + flex-direction: row; + gap: 17px; + } + + @include on-small-desktop { + grid-column: 7/-1; + } + + @include on-large-desktop { + grid-column: 9/-1; + } + } + + &__svg--1 { + opacity: 1; + } + &__svg--2 { + opacity: 0.5; + } + + &__svg--3 { + opacity: 0.2; + } + + &__svg--4 { + opacity: 0.1; + } + + &__svg--5 { + opacity: 0.05; + } + + &__svg--6 { + opacity: 0.03; + } + + &__svg--7 { + opacity: 0.02; + } + + &__svg--4, + &__svg--5, + &__svg--6, + &__svg--7 { + @include on-tablet { + display: none; + } + + @include on-small-desktop { + display: inline-block; + } + } +} diff --git a/src/styles/components/_body.scss b/src/styles/components/_body.scss new file mode 100644 index 000000000..7b18ae85d --- /dev/null +++ b/src/styles/components/_body.scss @@ -0,0 +1,36 @@ +.page_body { + overflow-x: hidden; + + font-family: Inter, sans-serif; + font-weight: 400; + font-style: normal; + color: $gray; + + background: linear-gradient(to right, #191536, #000); + background-repeat: no-repeat; + background-size: cover; +} + +.container { + padding-inline: 20px; + + @include on-tablet { + padding-inline: 34px; + } + + @include on-small-desktop { + padding-inline: 70px; + } + + @include on-desktop { + padding-inline: 110px; + } + + @include on-xxl-desktop { + padding-inline: 233px; + } +} + +.main { + background: transparent; +} diff --git a/src/styles/components/_burger.scss b/src/styles/components/_burger.scss new file mode 100644 index 000000000..4c9a05187 --- /dev/null +++ b/src/styles/components/_burger.scss @@ -0,0 +1,55 @@ +.burger { + position: relative; + + width: 20px; + height: 10px; + padding: 0; + border: none; + + background: transparent; + + &__line { + position: absolute; + height: 1px; + background: $white; + transition: 0.3s; + } + + &__line:nth-child(1) { + top: 0; + left: 0; + width: 16px; + } + + &__line:nth-child(2) { + top: 50%; + left: -4px; + transform: translateY(-50%); + width: 12px; + } + + &__line:nth-child(3) { + bottom: 0; + left: 0; + width: 16px; + } + + &.is-open { + .burger__line:nth-child(1) { + top: 50%; + transform: rotate(45deg); + width: 24px; + } + + .burger__line:nth-child(2) { + opacity: 0; + } + + .burger__line:nth-child(3) { + top: 50%; + bottom: auto; + transform: rotate(-45deg); + width: 24px; + } + } +} diff --git a/src/styles/components/_button.scss b/src/styles/components/_button.scss new file mode 100644 index 000000000..11018d391 --- /dev/null +++ b/src/styles/components/_button.scss @@ -0,0 +1,106 @@ +.button { + display: flex; + align-items: center; + justify-content: center; + + width: 280px; + height: 40px; + margin: 0 auto; + border-radius: 4px; + + font-size: 14px; + font-weight: 500; + line-height: 130%; + color: $white; + text-align: center; + + background-color: $color-accent; + + transition: + background-color $effectDuration ease, + color $effectDuration ease; + + &:hover { + color: $color-accent; + background-color: $white; + } + + &:active { + color: $dark-gray; + background-color: $btn-active; + } + + &:focus-visible { + color: $dark-gray; + background-color: $btn-active; + } + + @include on-tablet { + width: 458px; + height: 48px; + font-size: 16px; + } + + @include on-small-desktop { + width: 200px; + height: 48px; + } +} + +.buy-fixed { + position: fixed; + z-index: 9; + bottom: 0; + left: 0; + + display: flex; + justify-content: center; + + width: 100%; + padding: 30px 0; + + background: transparent; + + transition: opacity $effectDuration ease; + &::before { + pointer-events: none; + content: ''; + + position: absolute; + z-index: 0; + inset: 0; + + background: rgba(0, 0, 0, 1); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + + -webkit-mask-image: linear-gradient( + to top, + rgba(0, 0, 0, 1) 0%, + rgba(0, 0, 0, 1) 40%, + rgba(0, 0, 0, 0) 100% + ); + + mask-image: linear-gradient( + to top, + rgba(0, 0, 0, 1) 0%, + rgba(0, 0, 0, 1) 40%, + rgba(0, 0, 0, 0) 100% + ); + } + + @include on-small-desktop { + display: none; + } +} + +.buy-fixed.is-hidden { + pointer-events: none; + opacity: 0; +} + +/* кнопка поверх */ +.buy-fixed > * { + position: relative; + z-index: 1; +} diff --git a/src/styles/components/_checkout.scss b/src/styles/components/_checkout.scss new file mode 100644 index 000000000..346b78ee9 --- /dev/null +++ b/src/styles/components/_checkout.scss @@ -0,0 +1,536 @@ +.checkout { + position: fixed; + z-index: 1000; + inset: 0; + + overflow: hidden auto; + display: none; + + width: 100%; + height: 100vh; + padding: 20px 0; + padding-bottom: 37px; + + color: $white; + + background: linear-gradient(to right, #191536, #000); + background-repeat: no-repeat; + background-size: cover; + + -webkit-overflow-scrolling: touch; + + @include on-tablet { + padding: 30px 0; + } + + @include on-small-desktop { + padding: 100px 0; + } + + @include on-large-desktop { + padding: 158px 0; + } + + &--active { + display: block; + } + + &__content { + width: 100%; + margin: 0 auto; + } + + /* ---------- Header ---------- */ + + &__header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 30px; + } + + &__logo { + display: flex; + align-items: center; + text-decoration: none; + + img { + display: block; + width: auto; + height: 16px; + + @include on-tablet { + height: 20px; + } + } + } + + &__close { + display: flex; + align-items: center; + justify-content: center; + + width: 17px; + height: 17px; + + font-size: 24px; + line-height: 1; + color: $white; + + background: transparent; + + transition: color $effectDuration; + + &:hover { + color: $color-accent; + } + } + + /* ---------- Steps ---------- */ + + &__steps { + position: relative; + + display: flex; + align-items: center; + justify-content: space-between; + + margin-bottom: 30px; + padding-bottom: 17px; + + @include on-tablet { + margin-bottom: 41px; + padding-bottom: 10px; + } + + @include on-small-desktop { + margin-bottom: 102px; + } + } + + &__step { + cursor: pointer; + + flex: 1; + + padding: 0; + border: none; + + font-size: 12px; + font-weight: 500; + line-height: 130%; + color: $gray; + text-align: center; + + background: transparent; + + transition: color $effectDuration; + + @include on-tablet { + font-size: 14px; + } + + @include on-small-desktop { + position: relative; + + &::after { + content: ''; + + position: absolute; + bottom: -18px; + left: 50%; + transform: translateX(-50%); + + width: 4px; + height: 4px; + border-radius: 50%; + + transition: + opacity 0.3s, + background 0.3s; + } + + &--active::after { + background: $color-accent; + } + } + + &:hover { + color: $white; + } + + &--active { + color: $color-accent; + } + } + + /* ---------- Progress ---------- */ + + &__progress { + position: absolute; + bottom: 0; + left: 0; + + overflow: hidden; + + width: 100%; + height: 2px; + border-radius: 2px; + + background: rgba(255, 255, 255, 0.15); + + @include on-small-desktop { + display: none; + } + } + + &__progress-bar { + will-change: transform; + + display: block; + + width: 33.33%; + height: 100%; + + background: $color-accent; + + transition: transform 0.35s ease; + } + + &-page { + display: none; + animation: fade 0.25s ease; + + &--active { + display: block; + + @include on-desktop { + display: flex; + gap: 100px; + } + } + } + + @keyframes fade { + from { + opacity: 0; + } + + to { + opacity: 1; + } + } + + &-product { + display: flex; + flex-direction: column; + gap: 32px; + margin-bottom: 50px; + + @include on-tablet { + gap: 40px; + margin-bottom: 56px; + } + + @include on-small-desktop { + gap: 72px; + align-items: flex-start; + justify-content: space-between; + + margin-top: 29px; + margin-bottom: 0; + } + + &__image { + display: none; + + @include on-tablet { + display: flex; + align-items: center; + justify-content: center; + } + + @include on-small-desktop { + margin-left: -45px; + } + + &__img { + display: block; + + width: 100%; + max-width: 524px; + height: auto; + + object-fit: contain; + } + } + + &__info { + flex: 1; + + @include on-small-desktop { + flex: 0; + } + } + + &__row { + display: flex; + gap: 75px; + align-items: flex-start; + justify-content: space-evenly; + + @include on-tablet { + gap: 40px; + align-items: flex-end; + justify-content: space-between; + max-width: 347px; + } + } + + &__label { + margin-bottom: 10px; + margin-left: 6px; + + font-size: 16px; + line-height: 130%; + color: $gray; + + @include on-tablet { + margin-bottom: 20px; + } + } + &__select-wrapper { + position: relative; + width: 90px; + + &::after { + pointer-events: none; + content: ''; + + position: absolute; + top: 50%; + right: 11px; + transform: translateY(-50%); + + width: 9px; + height: 7px; + + background: url('../images/icons/arrow-down.svg') center / contain + no-repeat; + } + } + + &__select { + cursor: pointer; + + width: 100%; + height: 41px; + + font-size: 20px; + color: $white; + text-align: center; + text-align-last: center; + + background: #191536; + + transition: border-color $effectDuration; + + &:hover, + &:focus { + border-color: $color-accent; + outline: none; + } + + option { + color: $white; + background: $color-accent; + } + } + + &__price { + font-size: 26px; + font-weight: 500; + line-height: 100%; + color: $color-accent; + + @include on-tablet { + font-size: 36px; + } + } + } + + &-complete { + &__title { + margin-bottom: 20px; + font-size: 46px; + text-align: center; + text-transform: uppercase; + + @include on-tablet { + padding-inline: 97px; + } + } + + &__text { + margin-bottom: 50px; + + font-size: 18px; + font-weight: 400; + line-height: 130%; + text-align: center; + } + } + + &-form { + &__grid { + display: grid; + grid-template-columns: 1fr; + row-gap: 19px; + margin-bottom: 58px; + + @include on-tablet { + grid-template-columns: repeat(2, 1fr); + gap: 32px 30px; + } + } + + &__field { + position: relative; + display: block; + margin-bottom: 30px; + + @include on-tablet { + margin-bottom: 40px; + } + } + + &__label { + font-size: 14px; + color: $gray; + } + + &__select-wrapper { + position: relative; + width: 100%; + + &::after { + pointer-events: none; + content: ''; + + position: absolute; + top: 50%; + right: 12px; + transform: translateY(-50%); + + width: 9px; + height: 7px; + + background: url('../images/icons/arrow-down.svg') center / contain + no-repeat; + } + } + + &__select { + cursor: pointer; + + width: 100%; + height: 44px; + border: none; + + font-size: 16px; + color: $white; + + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background: $btn-active; + + transition: border-color $effectDuration; + + &:focus, + &:hover { + border-bottom-color: $color-accent; + outline: none; + } + + option { + color: $white; + background: $btn-active; + } + } + + &__input { + width: 100%; + height: 22px; + border: none; + border-bottom: 1px solid $dark-gray; + + font-size: 16px; + color: $white; + + background: transparent; + + transition: + border-color 0.3s, + color 0.3s; + + @include on-tablet { + height: 44px; + padding: 18px 0 0; + } + + &::placeholder { + color: transparent; + } + + &:focus { + border-bottom-color: $color-accent; + } + + &:focus + .checkout-form__label, + &:not(:placeholder-shown) + .checkout-form__label { + top: 0; + font-size: 12px; + color: $color-accent; + } + + &.touched:invalid { + border-bottom-color: #860404; + } + } + + &__card-row { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 16px; + + @include on-tablet { + gap: 24px; + } + } + + &__input--card { + text-align: center; + + @include on-tablet { + font-size: 18px; + } + } + + &__button { + width: 280px; + height: 40px; + font-size: 14px; + + @include on-tablet { + width: 458px; + height: 48px; + font-size: 16px; + } + + @include on-small-desktop { + width: 199px; + } + } + } +} diff --git a/src/styles/components/_faq-modal.scss b/src/styles/components/_faq-modal.scss new file mode 100644 index 000000000..08d110025 --- /dev/null +++ b/src/styles/components/_faq-modal.scss @@ -0,0 +1,124 @@ +.faq-modal { + position: fixed; + z-index: 1000; + inset: 0; + display: none; + + &.is-open { + display: block; + } + + &__overlay { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.6); + } + + &__window { + position: relative; + height: 100%; + padding: 68px 20px 20px; + background: #0f0f1a; + + @include on-tablet { + padding: 102px 33px 33px; + } + + @include on-small-desktop { + top: 50%; + transform: translateY(-50%); + + width: 880px; + max-height: 880px; + margin: 0 auto; + padding: 60px 90px 136px; + } + + @include on-large-desktop { + width: 1083px; + max-height: 793px; + padding: 70px 93px 50px; + } + } + + &__close { + top: 20px; + right: 20px; + } + + &__title { + margin-bottom: 37px; + + @include on-tablet { + margin-bottom: 30px; + } + + @include on-desktop { + margin-bottom: 50px; + } + } + + &__more { + margin-top: 20px; + } +} + +.faq { + margin-bottom: 50px; + + &__item { + overflow: hidden; + margin-bottom: 13px; + border: 1px solid $color-accent; + } + + &__question { + display: flex; + justify-content: space-between; + + width: 100%; + padding: 18px 25px 18px 29px; + border: none; + + font-size: 16px; + line-height: 150%; + color: $color-accent; + + background: transparent; + } + + &__icon { + flex-shrink: 0; + width: 9px; + height: 6px; + transition: transform 0.3s; + } + + &__item.is-open &__icon { + transform: rotate(-90deg); + } + + &__answer { + display: none; + padding: 18px; + padding-top: 0; + color: white; + + &-text { + margin-bottom: 20px; + font-size: 16px; + line-height: 150%; + color: $gray; + } + } + + &__item.is-open &__answer { + display: block; + } + + &__meta { + font-size: 14px; + line-height: 150%; + color: #545454; + } +} diff --git a/src/styles/components/_footer.scss b/src/styles/components/_footer.scss new file mode 100644 index 000000000..1a4f796f8 --- /dev/null +++ b/src/styles/components/_footer.scss @@ -0,0 +1,338 @@ +.footer { + padding-top: 50px; + padding-bottom: 50px; + background-color: #05040b; + + &__contact { + padding-bottom: 50px; + + @include on-tablet { + @include page-grid; + } + } + + &__info { + @include on-tablet { + grid-column: 1/4; + } + + @include on-small-desktop { + grid-column: 1/5; + } + } + + &__subtitle { + display: block; + margin-bottom: 11px; + font-size: 14px; + color: $color-accent; + + @include on-small-desktop { + margin-bottom: 13px; + } + } + + &__title { + margin-bottom: 32px; + + @include on-tablet { + margin-bottom: 50px; + } + + @include on-small-desktop { + margin-bottom: 26px; + } + } + + &__description { + margin-bottom: 50px; + + @include on-tablet { + margin-bottom: 76px; + } + + &--tablet { + display: none; + + @include on-tablet { + display: block; + } + } + } + + &__contacts { + display: flex; + flex-direction: column; + gap: 12px; + + &--tablet { + display: none; + + @include on-tablet { + display: flex; + } + } + + &--mobile { + display: flex; + margin-bottom: 22px; + font-size: 13px; + line-height: 100%; + + @include on-tablet { + display: none; + } + } + } + + &__phone, + &__email { + transition: color $effectDuration ease; + + &:hover { + color: $white; + } + } + + &__form { + width: 100%; + + @include on-tablet { + grid-column: 4/-1; + } + + @include on-small-desktop { + grid-column: 7/-1; + } + + @include on-large-desktop { + grid-column: 9/-1; + } + } + + &__field { + position: relative; + display: block; + margin-bottom: 40px; + + &--message { + margin-bottom: 48px; + } + } + + &__textarea { + resize: none; + height: 67px; + min-height: 67px; + padding-top: 18px; + } + + &__label { + pointer-events: none; + + position: absolute; + top: 0; + left: 0; + + font-size: 14px; + line-height: 150%; + color: $gray; + + transition: + top 0.3s, + color 0.3s, + font-size 0.3s; + + &--error { + position: absolute; + top: 0; + left: 0; + + display: none; + + font-size: 12px; + line-height: 1; + color: #860404; + } + } + + &__input, + &__textarea { + width: 100%; + height: 44px; + padding: 18px 0 0; + border: none; + border-bottom: 1px solid $dark-gray; + + font-size: 16px; + color: $white; + + background: transparent; + + transition: + border-color 0.3s, + color 0.3s; + + &::placeholder { + color: transparent; + } + + &:focus { + border-bottom-color: $color-accent; + } + + &:focus + .footer__label, + &:not(:placeholder-shown) + .footer__label { + top: 0; + font-size: 12px; + color: $color-accent; + } + + &.touched:invalid { + border-bottom-color: #860404; + } + } + + &__input.touched:invalid ~ .footer__error--empty, + &__textarea.touched:invalid ~ .footer__error--empty { + display: block; + } + + &__input[type='email'].touched:invalid:not(:placeholder-shown) + ~ .footer__error--invalid { + display: block; + } + + &__actions { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 32px; + } + + &__button { + @include on-tablet { + width: 200px; + } + } + + &__scroll-top { + display: none; + + width: 48px; + height: 48px; + border: 1px solid $color-accent; + border-radius: 50%; + + color: $color-accent; + + background: transparent; + + transition: + background-color $effectDuration ease, + color $effectDuration ease; + + &:hover { + color: $white; + background-color: $color-accent; + } + + @include on-tablet { + display: block; + } + } + + &__note { + margin-top: 30px; + font-size: 12px; + + @include on-tablet { + display: none; + } + } + + &__bottom { + padding-top: 45px; + + @include on-tablet { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + } + } + + &__logo { + display: flex; + + width: 69px; + height: 14px; + margin-bottom: 12px; + + transition: + opacity $effectDuration ease, + visibility $effectDuration ease; + + @include on-tablet { + margin-right: 127px; + } + + @include on-small-desktop { + width: 72px; + margin-right: 0; + margin-bottom: 0; + } + } + + &__content { + display: flex; + flex-direction: row; + gap: 99px; + justify-content: space-between; + } + + &__nav { + display: flex; + flex-direction: column; + gap: 12px; + + @include on-tablet { + flex-direction: row; + gap: 43px; + } + + &-link { + font-size: 13px; + line-height: 150%; + color: $white; + transition: color $effectDuration ease; + + &:hover { + color: $color-accent; + } + } + } + + &__socials { + display: flex; + flex-direction: row; + gap: 22px; + + @include on-tablet { + gap: 18px; + } + } + + &__social { + &-icon { + display: block; + width: 15px; + height: 14px; + transition: transform $effectDuration ease; + + &:hover { + transform: scale(1.2); + } + } + } +} diff --git a/src/styles/components/_header.scss b/src/styles/components/_header.scss new file mode 100644 index 000000000..8e40d646d --- /dev/null +++ b/src/styles/components/_header.scss @@ -0,0 +1,355 @@ +.header { + padding-top: 20px; + padding-bottom: 46px; + + @include on-tablet { + padding-top: 30px; + padding-bottom: 61px; + } + + @include on-small-desktop { + padding-top: 47px; + padding-bottom: 84px; + } + + @include on-xxl-desktop { + padding-bottom: 107px; + } + + &__top { + display: flex; + align-items: center; + justify-content: space-between; + padding-bottom: 17px; + + @include on-tablet { + margin-bottom: 38px; + } + + @include on-desktop { + margin-bottom: 95px; + } + + @include on-xxl-desktop { + margin-bottom: 230px; + } + } + + &__logo { + width: 48px; + height: 10px; + margin-right: 35px; + transition: + opacity $effectDuration ease, + visibility $effectDuration ease; + + @include on-tablet { + width: 67px; + height: 14px; + } + + @include on-small-desktop { + width: 78px; + height: 16px; + } + + &.hide { + visibility: hidden; + opacity: 0; + } + } + + &__right { + display: none; + + @include on-small-desktop { + display: flex; + gap: 37px; + align-items: center; + } + } + + &__nav { + display: none; + + @include on-small-desktop { + display: flex; + gap: 36px; + } + } + + &__link { + font-size: 21px; + font-weight: 500; + line-height: 130%; + color: $white; + + transition: color $effectDuration ease; + + &:hover { + color: $color-accent; + } + + @include on-small-desktop { + font-size: 16px; + } + + &--mobile { + padding: 11px 22px; + transition: background $effectDuration ease; + + &:hover { + width: 100%; + background: #110e25; + } + + @include on-tablet { + padding: 11px 154px; + } + } + } + + &__burger { + position: relative; + z-index: 20; + + display: flex; + flex-direction: column; + gap: 4px; + + border: none; + + background: none; + + @include on-small-desktop { + display: none; + } + } + + &__content { + display: flex; + flex-direction: column; + + @include on-tablet { + position: relative; + flex-direction: row-reverse; + justify-content: space-between; + } + + @include on-desktop { + margin-bottom: 84px; + } + + @include on-large-desktop { + gap: 100px; + margin-bottom: 237px; + } + } + + &__title { + margin-bottom: 17px; + + @include on-desktop { + margin-bottom: 19px; + } + + @include on-large-desktop { + margin-bottom: 35px; + } + } + + &__description { + padding-bottom: 8px; + font-weight: 500; + + @include on-tablet { + margin-bottom: 10px; + } + + @include on-desktop { + padding-right: 137px; + padding-left: 92px; + } + + @include on-large-desktop { + margin-bottom: 30px; + padding-right: 21px; + } + } + + &__price { + margin: 0 auto; + margin-bottom: 16px; + + font-size: 18px; + font-weight: 500; + line-height: 100%; + color: $white; + + @include on-tablet { + margin-bottom: 24px; + margin-left: 0; + } + + @include on-desktop { + margin-bottom: 20px; + margin-left: 92px; + } + + @include on-large-desktop { + margin-bottom: 36px; + font-size: 20px; + } + } + + &__media { + display: block; + width: 100%; + min-width: 280px; + + @include on-tablet { + position: relative; + z-index: 1; + right: 0; + + width: 60%; + min-width: 486px; + height: 219px; + + object-fit: contain; + } + + @include on-small-desktop { + height: 339px; + } + } + + &__image { + width: 100%; + height: auto; + object-fit: cover; + + @include on-tablet { + content: url('../images/header-images/image-tablet.png'); + height: 100%; + } + + @include on-small-desktop { + content: url('../images/header-images/image-desktop.png'); + } + + @include on-xxl-desktop { + content: url('../images/header-images/image-xxl.png'); + } + } + + &__info { + display: flex; + flex-direction: column; + + @include on-tablet { + position: relative; + z-index: 2; + left: 0; + + width: 60%; + margin-right: -100px; + } + } + + &__bottom { + display: none; + + @include on-small-desktop { + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: space-between; + + width: 100%; + } + + &__slider { + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: space-between; + } + + &-nav-button { + font-size: 16px; + font-weight: 500; + line-height: 150%; + color: $white; + + transition: color $effectDuration ease; + + &:hover { + color: $color-accent; + } + } + + &-link:first-child { + margin-right: 39px; + } + + &-more { + margin-left: 130px; + + &-text, + &-svg { + color: inherit; + transition: color $effectDuration ease; + } + } + } + + &-slider { + position: relative; + + display: flex; + align-items: flex-start; + justify-content: space-between; + + width: 207px; + height: 35px; + + &__prev, + &__next { + cursor: pointer; + border: none; + color: $gray; + background: transparent; + } + + &__progress { + position: absolute; + bottom: 0; + left: 0; + + overflow: hidden; + display: flex; + + width: 207px; + height: 1px; + } + + &__item { + flex: 1; + background: #212121; + } + + &__active { + position: absolute; + bottom: 0; + left: 0; + + width: 33.33%; + height: 1px; + + background: $color-accent; + + transition: transform 0.35s ease; + } + } +} diff --git a/src/styles/components/_help-modal.scss b/src/styles/components/_help-modal.scss new file mode 100644 index 000000000..8c9f6bb75 --- /dev/null +++ b/src/styles/components/_help-modal.scss @@ -0,0 +1,121 @@ +.help-modal { + position: fixed; + z-index: 999; + inset: 0; + display: none; + + &.is-open { + display: block; + } + + &__overlay { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.7); + } + + &__window { + position: relative; + top: 0; + + width: 100%; + padding: 68px 20px 73px; + + background: $btn-active; + + @include on-tablet { + padding: 102px 33px 124px 35px; + } + + @include on-small-desktop { + top: 50%; + transform: translateY(-50%); + + width: min(880px, 90vw); + margin: 0 auto; + padding: 60px 90px 80px; + } + + @include on-large-desktop { + width: min(1083px, 90vw); + padding: 60px 93px 86px; + } + } + + &__close { + top: 20px; + right: 20px; + } + + &__title { + margin-bottom: 30px; + + @include on-desktop { + margin-bottom: 50px; + } + } + + &__text { + margin-bottom: 30px; + } + + &__link { + margin-bottom: 15px; + color: $color-accent; + transition: color $effectDuration ease; + + &:hover { + color: $white; + } + } + + &__description { + margin-bottom: 40px; + color: $gray; + } + + &__icon { + color: $color-accent; + } + + &__grid { + display: flex; + flex-direction: column; + gap: 18px; + } + + &__contacts { + display: flex; + flex-direction: column; + gap: 30px; + text-align: left; + + @include on-tablet { + display: grid; + grid-template-columns: 260px 1fr; + column-gap: 65px; + } + } + + &__section { + display: flex; + flex-direction: column; + gap: 20px; + + &--1 { + color: $color-accent; + } + + &--2 { + color: $gray; + } + } + + &__contact-link { + transition: color $effectDuration ease; + + &:hover { + color: $white; + } + } +} diff --git a/src/styles/components/_lang-switch.scss b/src/styles/components/_lang-switch.scss new file mode 100644 index 000000000..9e0bc4403 --- /dev/null +++ b/src/styles/components/_lang-switch.scss @@ -0,0 +1,130 @@ +.lang { + position: relative; + + display: none; + + font-weight: 500; + line-height: 130%; + color: $color-accent; + + @include on-small-desktop { + display: inline-block; + } + + /* ========================= + DROPDOWN + ========================= */ + + &__dropdown { + scrollbar-color: $color-accent transparent; + scrollbar-width: thin; + + position: absolute; + z-index: 50; + top: calc(100% + 6px); + left: 0; + + overflow-y: auto; + display: none; + flex-direction: column; + gap: 12px; + + min-width: max-content; + max-height: 160px; + padding: 12px; + border-radius: 4px; + + background: $btn-active; + + &::-webkit-scrollbar { + width: 1px; + } + + &::-webkit-scrollbar-thumb { + background: $color-accent; + } + } + + /* ========================= + OPEN STATE + ========================= */ + + &.is-open { + .lang__dropdown { + display: flex; + } + } + + /* ========================= + BUTTON + ========================= */ + + &__btn { + cursor: pointer; + + display: flex; + gap: 6px; + align-items: center; + + padding: 0; + border: none; + + color: inherit; + + background: transparent; + } + + &__current { + display: inline-block; + } + + /* ========================= + ARROW + ========================= */ + + &__arrow { + width: 8px; + height: 5px; + + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'%3E%3Cpath d='M3.89746 4.5L0 0L7.79458 0L3.89746 4.5Z' fill='%2305C2DF'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-size: contain; + } + + /* ========================= + OPTIONS + ========================= */ + + &__option { + cursor: pointer; + color: $color-accent; + white-space: nowrap; + transition: 0.2s ease; + + &:hover, + &.is-hover { + color: $white; + } + + &.is-active { + color: $white; + } + } + + /* ========================= + INDICATOR + ========================= */ + + &__indicator { + position: absolute; + top: 30px; + right: 0; + + width: 0.5px; + height: 18px; + + background: $color-accent; + + transition: transform $effectDuration ease; + } +} diff --git a/src/styles/components/_mobile-menu.scss b/src/styles/components/_mobile-menu.scss new file mode 100644 index 000000000..3b6b8e395 --- /dev/null +++ b/src/styles/components/_mobile-menu.scss @@ -0,0 +1,24 @@ +.mobile-menu { + position: fixed; + z-index: 10; + inset: 0; + + display: flex; + flex-direction: column; + align-items: start; + justify-content: center; + + width: 100%; + height: 100vh; + + visibility: hidden; + opacity: 0; + background: $color-background-dark; + + transition: $effectDuration ease; + + &.is-open { + visibility: visible; + opacity: 1; + } +} diff --git a/src/styles/components/_modal-close.scss b/src/styles/components/_modal-close.scss new file mode 100644 index 000000000..33f6dcd6f --- /dev/null +++ b/src/styles/components/_modal-close.scss @@ -0,0 +1,49 @@ +.modal-close { + position: absolute; + top: 20px; + right: 20px; + + display: flex; + align-items: center; + justify-content: center; + + width: 17px; + height: 17px; + padding: 0; + border: none; + + color: $white; + + background: transparent; + + transition: color $effectDuration ease; + + &:hover { + color: $color-accent; + } + + @include on-tablet { + top: 34px; + right: 34px; + } + + @include on-desktop { + top: 18px; + right: 18px; + } + + @include on-xxl-desktop { + top: 28px; + right: 28px; + } + + &__icon { + width: 100%; + height: 100%; + + line, + path { + stroke: currentColor; + } + } +} diff --git a/src/styles/components/_more-button.scss b/src/styles/components/_more-button.scss new file mode 100644 index 000000000..83ee6bdb0 --- /dev/null +++ b/src/styles/components/_more-button.scss @@ -0,0 +1,19 @@ +.more-button { + display: flex; + flex-direction: column; + gap: 7px; + align-items: center; + + color: $color-accent; + + transition: color $effectDuration ease; + + &:hover { + color: $white; + } + + &-icon { + color: inherit; + transition: color $effectDuration ease; + } +} diff --git a/src/styles/components/_more-than.scss b/src/styles/components/_more-than.scss new file mode 100644 index 000000000..4e3a6ddb1 --- /dev/null +++ b/src/styles/components/_more-than.scss @@ -0,0 +1,185 @@ +.more-than { + padding: 50px 0; + background-color: #05040b; + + @include on-tablet { + padding: 70px 0; + } + + @include on-small-desktop { + padding: 100px 0; + } + + @include on-large-desktop { + padding: 158px 0; + } + + &__title { + margin-bottom: 12px; + + @include on-tablet { + text-align: center; + } + } + + &__description { + margin-bottom: 30px; + font-size: 12px; + line-height: 100%; + color: $color-accent; + + @include on-tablet { + margin-bottom: 37px; + text-align: center; + } + + @include on-desktop { + margin-bottom: 70px; + font-style: 14px; + } + } + + &__grid { + @include page-grid; + + gap: 20px; + + @include on-tablet { + column-gap: 40px; + } + } + + &__item { + grid-column: 1/-1; + justify-content: start; + + @include on-tablet { + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + + text-align: center; + } + + &--1, + &--3 { + @include on-tablet { + grid-column: 1/4; + } + } + + &--2, + &--4 { + @include on-tablet { + grid-column: 4/-1; + } + } + + &--1 { + @include on-small-desktop { + grid-column: 1/4; + } + + @include on-large-desktop { + grid-column: 1/5; + } + } + + &--2 { + @include on-small-desktop { + grid-column: 4/7; + } + + @include on-large-desktop { + grid-column: 5/9; + } + } + &--3 { + @include on-small-desktop { + grid-column: 7/10; + } + + @include on-large-desktop { + grid-column: 9/13; + } + } + &--4 { + @include on-small-desktop { + grid-column: 10/-1; + } + + @include on-large-desktop { + grid-column: 13/-1; + } + } + + &-title { + margin-bottom: 11px; + + @include on-tablet { + margin-bottom: 18px; + } + } + } + + &__icon { + display: none; + + @include on-tablet { + display: block; + } + + &--education { + width: 98px; + height: 81px; + + @include on-tablet { + margin-bottom: 33px; + } + + @include on-small-desktop { + margin-bottom: 32px; + } + } + + &--estate { + width: 84px; + height: 84px; + + @include on-tablet { + margin-bottom: 30px; + } + + @include on-small-desktop { + margin-bottom: 29px; + } + } + + &--fitness { + width: 113px; + height: 83px; + + @include on-tablet { + margin-bottom: 31px; + } + + @include on-small-desktop { + margin-bottom: 30px; + } + } + + &--interactions { + width: 83px; + height: 83px; + + @include on-tablet { + margin-bottom: 31px; + } + + @include on-small-desktop { + margin-bottom: 30px; + } + } + } +} diff --git a/src/styles/components/_slider-navigation.scss b/src/styles/components/_slider-navigation.scss new file mode 100644 index 000000000..0d4d621d3 --- /dev/null +++ b/src/styles/components/_slider-navigation.scss @@ -0,0 +1,46 @@ +.slider { + position: relative; + + flex-direction: row; + align-items: flex-start; + justify-content: space-between; + + width: 207px; + height: 35px; + + &-nav-button { + position: static; + color: $gray; + } + + &-progress { + position: absolute; + bottom: 0; + left: 0; + + overflow: hidden; + display: flex; + + width: 207px; + height: 1px; + margin-top: 10px; + + &-item { + flex: 1; + background: #212121; + } + + &-active { + position: absolute; + bottom: 0; + left: 0; + + width: 33.33%; + height: 1px; + + background: $color-accent; + + transition: transform 0.35s ease; + } + } +} diff --git a/src/styles/components/_svg-button.scss b/src/styles/components/_svg-button.scss new file mode 100644 index 000000000..82c8f0787 --- /dev/null +++ b/src/styles/components/_svg-button.scss @@ -0,0 +1,16 @@ +.play-button { + width: auto; + height: 66px; + color: $color-accent; + + &__triangle { + width: 24px; + height: 23px; + color: $color-accent; + + &:hover, + &:active { + color: $white; + } + } +} diff --git a/src/styles/components/_tech-specs.scss b/src/styles/components/_tech-specs.scss new file mode 100644 index 000000000..356cbd954 --- /dev/null +++ b/src/styles/components/_tech-specs.scss @@ -0,0 +1,253 @@ +.tech { + &-specs { + position: relative; + padding: 50px 0; + background-color: #05040b; + + @include on-small-desktop { + padding: 100px 0; + } + + &__title { + margin-bottom: 41px; + + @include on-small-desktop { + max-width: 854px; + margin: 0 auto; + margin-bottom: 141px; + text-align: right; + } + } + + &__layout { + position: relative; + } + + // IMAGE WRAPPER + &__media { + position: relative; + width: 100%; + max-width: 197px; + margin: 0 auto; + + @include on-tablet { + max-width: 358px; + } + + @include on-small-desktop { + max-width: 297px; + } + } + + &__image { + display: block; + width: 100%; + height: auto; + } + + &__line { + display: none; + + @include on-small-desktop { + pointer-events: none; + position: absolute; + z-index: 2; + display: block; + } + + &--1 { + top: -18%; + right: 149px; + width: 320px; + + @include on-desktop { + width: 403px; + } + } + + &--2 { + top: -23%; + left: 149px; + } + + &--3 { + right: 291px; + bottom: 41%; + } + + &--decor { + right: 260px; + bottom: 17%; + } + } + } +} + +/* ========================= + SPEC POINT (HOTSPOTS) +========================= */ + +.spec-point { + position: absolute; + z-index: 5; + transform: translate(-50%, -50%); + + @include on-small-desktop { + display: none; + } + + &--sensor { + top: 4%; + left: 38%; + + @include on-tablet { + left: 29%; + } + } + + &--connection { + top: 88%; + left: 4%; + } + + &--battery { + top: 50%; + left: 75%; + } + + &__btn { + position: relative; + + width: 34px; + height: 34px; + border: 2px solid #ffffff24; + border-radius: 50%; + + background: $color-accent; + + transition: + background-color 0.2s ease, + border-color 0.2s ease; + + // PLUS + &::before, + &::after { + content: ''; + position: absolute; + background: #fff; + transition: + transform 0.2s ease, + opacity 0.2s ease; + } + + &::before { + left: 10px; + width: 11px; + height: 1px; + } + + &::after { + top: 10px; + width: 1px; + height: 11px; + } + + &:hover { + border-color: #ffffff24; + background-color: #07798b; + } + } + + &__popup { + position: absolute; + z-index: 20; + transform: translateX(-28%); + + display: none; + + min-width: 168px; + padding: 17px 11px 22px; + border-radius: 4px; + + color: $gray; + + background: #191536; + + @include on-tablet { + top: 0; + left: 124px; + transform: translateX(-50%); + } + } + + &__title { + display: none; + margin-bottom: 6px; + font-size: 18px; + font-weight: 900; + + @include on-small-desktop { + display: block; + margin-bottom: 21px; + } + } + + &__text { + font-size: 12px; + } + + &.is-active { + z-index: 8; + + .spec-point__btn { + // PLUS → MINUS + &::after { + opacity: 0; + } + } + + .spec-point__popup { + display: block; + } + } + + &__details { + display: none; + + @include on-small-desktop { + position: absolute; + z-index: 3; + inset: 0; + display: block; + } + + @include on-large-desktop { + padding-right: 85px; + padding-left: 192px; + } + } + + &__detail { + position: absolute; + + &--sensor { + top: -60px; + left: -263px; + + @include on-desktop { + left: -353px; + } + } + + &--batteries { + top: -75px; + right: -331px; + max-width: 265px; + } + + &--connection { + top: 161px; + left: -267px; + } + } +} diff --git a/src/styles/components/_video-modal.scss b/src/styles/components/_video-modal.scss new file mode 100644 index 000000000..1fbc4f43d --- /dev/null +++ b/src/styles/components/_video-modal.scss @@ -0,0 +1,57 @@ +.video-modal { + position: fixed; + z-index: 9999; + inset: 0; + + display: none; + align-items: center; + justify-content: center; + + width: 100%; + height: 100%; + + background: rgba(0, 0, 0, 0.7); + + &.is-open { + display: flex; + } + + &__window { + position: relative; + + overflow: hidden; + + width: 876px; + height: 486px; + border-radius: 4px; + + background: #000; + + animation: show-video 0.25s ease; + + @media (max-width: 900px) { + aspect-ratio: 16 / 9; + width: 90vw; + height: auto; + } + } + + &__video { + width: 100%; + height: 100%; + border: 0; + } +} + +/* ANIMATION */ +@keyframes show-video { + from { + transform: scale(0.9); + opacity: 0; + } + + to { + transform: scale(1); + opacity: 1; + } +} diff --git a/src/styles/components/_why-kat.scss b/src/styles/components/_why-kat.scss new file mode 100644 index 000000000..1bd62fc81 --- /dev/null +++ b/src/styles/components/_why-kat.scss @@ -0,0 +1,156 @@ +.why-kat { + padding: 50px 0; + background: linear-gradient(to right, #191536, #000); + background-repeat: no-repeat; + background-size: cover; + + @include on-tablet { + padding: 70px 0; + } + + @include on-small-desktop { + padding: 100px 0; + } + + @include on-large-desktop { + padding: 158px 0; + } + + &__title { + margin-bottom: 32px; + + @include on-tablet { + margin-bottom: 30px; + text-align: center; + } + } + + &__grid { + @include page-grid; + + gap: 20px; + + @include on-tablet { + column-gap: 23px; + } + } + + &__item { + grid-column: 1/-1; + justify-content: start; + + @include on-tablet { + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + + text-align: center; + } + + &--1 { + @include on-tablet { + grid-column: 1/3; + } + + @include on-small-desktop { + grid-column: 1/5; + } + } + + &--2 { + @include on-tablet { + grid-column: 3/5; + } + + @include on-small-desktop { + grid-column: 5/9; + } + + @include on-large-desktop { + grid-column: 7/11; + } + } + + &--3 { + @include on-tablet { + grid-column: 5/-1; + } + + @include on-small-desktop { + grid-column: 9/-1; + } + + @include on-large-desktop { + grid-column: 13/-1; + } + } + + &-title { + margin-bottom: 11px; + + @include on-tablet { + margin-bottom: 18px; + } + } + } + + &__icon { + display: none; + + @include on-tablet { + display: block; + } + + &--compatible { + width: 80px; + height: 81px; + + @include on-tablet { + margin-bottom: 34px; + } + + @include on-small-desktop { + margin-bottom: 32px; + } + } + + &--control-panel { + width: 89px; + height: 80px; + + @include on-tablet { + margin-bottom: 30px; + } + + @include on-small-desktop { + margin-bottom: 29px; + } + } + + &--sensors { + width: 105px; + height: 80px; + + @include on-tablet { + margin-bottom: 31px; + } + + @include on-small-desktop { + margin-bottom: 30px; + } + } + } + &__button { + display: none; + margin-top: 90px; + + @include on-small-desktop { + display: block; + } + + @include on-large-desktop { + display: none; + } + } +} diff --git a/src/styles/main.scss b/src/styles/main.scss index fb9195d12..de8f206a7 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -1,7 +1,26 @@ -@import 'utils'; -@import 'fonts'; -@import 'typography'; +@import 'utils/vars'; +@import 'utils/mixins'; +@import 'utils/extends'; -body { - background: $c-gray; -} +@import 'base/typography'; +@import 'base/reset'; + +@import 'components/body'; +@import 'components/header'; +@import 'components/burger'; +@import 'components/button'; +@import 'components/lang-switch'; +@import 'components/mobile-menu'; +@import 'components/svg-button'; +@import 'components/video-modal'; +@import 'components/faq-modal'; +@import 'components/more-button'; +@import 'components/modal-close'; +@import 'components/help-modal'; +@import 'components/more-than'; +@import 'components/about-product'; +@import 'components/slider-navigation'; +@import 'components/tech-specs'; +@import 'components/why-kat'; +@import 'components/footer'; +@import 'components/checkout'; diff --git a/src/styles/utils/_extends.scss b/src/styles/utils/_extends.scss index d7201e7b3..d606b9547 100644 --- a/src/styles/utils/_extends.scss +++ b/src/styles/utils/_extends.scss @@ -1,4 +1,51 @@ %h1 { - font-family: Roboto, sans-serif; + font-size: 26px; + line-height: 130%; + + @include on-desktop { + font-size: 46px; + } + + @include on-large-desktop { + font-size: 54px; + } +} + +%h2 { + font-size: 21px; + line-height: 130%; + + @include on-small-desktop { + font-size: 36px; + } +} + +%h3 { + font-size: 18px; + font-weight: 900; + line-height: 100%; + color: $white; + text-transform: uppercase; + + @include on-desktop { + font-size: 18px; + } +} + +%h4 { + font-size: 18px; + font-weight: 700; + line-height: 22px; + + @include on-desktop { + font-size: 34px; + line-height: 42px; + } +} + +%p { + font-size: 16px; font-weight: 400; + line-height: 150%; + color: $gray; } diff --git a/src/styles/utils/_mixins.scss b/src/styles/utils/_mixins.scss index 80c79780d..2c2902ca0 100644 --- a/src/styles/utils/_mixins.scss +++ b/src/styles/utils/_mixins.scss @@ -4,3 +4,65 @@ #{$_property}: $_toValue; } } + +@mixin on-small-tablet() { + @media (min-width: $small-tablet-min-width) { + @content; + } +} + +@mixin on-tablet() { + @media (min-width: $tablet-min-width) { + @content; + } +} + +@mixin on-laptop() { + @media (min-width: $laptop-min-width) { + @content; + } +} + +@mixin on-small-desktop() { + @media (min-width: $small-desktop-min-width) { + @content; + } +} + +@mixin on-desktop() { + @media (min-width: $desktop-min-width) { + @content; + } +} + +@mixin on-large-desktop() { + @media (min-width: $large-desktop-min-width) { + @content; + } +} + +@mixin on-xxl-desktop() { + @media (min-width: $xxl-desktop-min-width) { + @content; + } +} + +@mixin page-grid() { + --columns: 2; + + display: grid; + grid-template-columns: repeat(var(--columns), 1fr); + column-gap: 20px; + + @include on-tablet { + --columns: 6; + } + + @include on-small-desktop { + --columns: 12; + } + + @include on-large-desktop { + --columns: 16; + } +} diff --git a/src/styles/utils/_vars.scss b/src/styles/utils/_vars.scss index aeb006ffb..638ca5eb9 100644 --- a/src/styles/utils/_vars.scss +++ b/src/styles/utils/_vars.scss @@ -1 +1,13 @@ -$c-gray: #eee; +$gray: #929292; +$color-accent: #05c2df; +$white: #fff; +$btn-active: #191536; +$dark-gray: #2f2f2f; +$color-background-dark: #191536; +$small-tablet-min-width: 568px; +$tablet-min-width: 768px; +$small-desktop-min-width: 960px; +$desktop-min-width: 1280px; +$large-desktop-min-width: 1440px; +$xxl-desktop-min-width: 1920px; +$effectDuration: 0.3s;