├── public
├── robots.txt
├── scene.glb
├── scene-black.glb
├── manifest.json
├── logo.svg
└── vite.svg
├── src
├── assets
│ ├── images
│ │ ├── iphone-14.jpg
│ │ ├── iphone-hand.png
│ │ ├── logo-animated.gif
│ │ ├── search.svg
│ │ ├── store.svg
│ │ └── logo.svg
│ └── react.svg
├── main.jsx
├── components
│ ├── DisplaySection.jsx
│ ├── Navbar.jsx
│ ├── SoundSection.jsx
│ ├── Jumbotron.jsx
│ └── WebGiViewer.jsx
├── App.jsx
├── utils
│ └── scroll-animation.js
└── index.css
├── vite.config.js
├── .gitignore
├── index.html
└── package.json
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/public/scene.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abdallahabusidu/AppleWebiste3D/HEAD/public/scene.glb
--------------------------------------------------------------------------------
/public/scene-black.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abdallahabusidu/AppleWebiste3D/HEAD/public/scene-black.glb
--------------------------------------------------------------------------------
/src/assets/images/iphone-14.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abdallahabusidu/AppleWebiste3D/HEAD/src/assets/images/iphone-14.jpg
--------------------------------------------------------------------------------
/src/assets/images/iphone-hand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abdallahabusidu/AppleWebiste3D/HEAD/src/assets/images/iphone-hand.png
--------------------------------------------------------------------------------
/src/assets/images/logo-animated.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abdallahabusidu/AppleWebiste3D/HEAD/src/assets/images/logo-animated.gif
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App";
4 | import "./index.css";
5 |
6 | ReactDOM.createRoot(document.getElementById("root")).render();
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | iPhone 14
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/assets/images/search.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/src/assets/images/store.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/images/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/DisplaySection.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | function DisplaySection({ triggerPreview }) {
4 | const handelLearnMore = () => {
5 | window.scrollTo({ top: 0, left: 0, behavior: "smooth" });
6 | };
7 | return (
8 |
9 |
New
10 |
Brilliant.
11 |
12 | A display that's up to 2x brighter in the sun.
13 |
14 |
17 |
20 |
21 | );
22 | }
23 |
24 | export default DisplaySection;
25 |
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import DisplaySection from "./components/DisplaySection";
3 | import Jumbotron from "./components/Jumbotron";
4 | import Navbar from "./components/Navbar";
5 | import WebGiViewer from "./components/WebGiViewer";
6 | import SoundSection from "./components/SoundSection";
7 |
8 | function App() {
9 | const webGiViewerRef = React.useRef();
10 | const contentRef = React.useRef();
11 | const handlePreview = () => {
12 | webGiViewerRef.current.triggerPreview();
13 | };
14 | return (
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
27 | export default App;
28 |
--------------------------------------------------------------------------------
/src/components/Navbar.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Logo from "../assets/images/logo.svg";
3 | import Search from "../assets/images/search.svg";
4 | import Store from "../assets/images/store.svg";
5 | function Navbar() {
6 | let links = [
7 | "Store",
8 | "Mac",
9 | "iPad",
10 | "iPhone",
11 | "Watch",
12 | "AirPods",
13 | "Tv & Home",
14 | "Entertainment",
15 | "Accessories",
16 | "Support",
17 | ];
18 | return (
19 |
42 | );
43 | }
44 |
45 | export default Navbar;
46 |
--------------------------------------------------------------------------------
/src/components/SoundSection.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | function SoundSection() {
4 | const handelLearnMore = () => {
5 | const element = document.querySelector(".display-section");
6 | window.scrollTo({
7 | top: element?.getBoundingClientRect().bottom,
8 | left: 0,
9 | behavior: "smooth",
10 | });
11 | };
12 | return (
13 |
14 |
15 |
16 |
New Sound System
17 |
Feel the base.
18 |
19 | From $41.62/mo. for 24 mo. or $999 before trade-in
20 |
21 |
31 |
32 |
33 |
34 | );
35 | }
36 |
37 | export default SoundSection;
38 |
--------------------------------------------------------------------------------
/src/components/Jumbotron.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Iphone from "../assets/images/iphone-14.jpg";
3 | import HoldingIphone from "../assets/images/iphone-hand.png";
4 | function Jumbotron() {
5 | const handelLearnMore = () => {
6 | const element = document.querySelector(".sound-section");
7 | window.scrollTo({
8 | top: element?.getBoundingClientRect().top,
9 | left: 0,
10 | behavior: "smooth",
11 | });
12 | };
13 | return (
14 |
15 |
New
16 |

17 |
Big and bigger
18 |
19 | From $1099 or $45.79/mo. per month for 24 mo.months before
20 | trade‑inFootnote*
21 |
22 |
32 |

33 |
34 | );
35 | }
36 |
37 | export default Jumbotron;
38 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-react-app",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0",
14 | "@studio-freight/lenis": "^0.2.28",
15 | "@testing-library/jest-dom": "^5.16.5",
16 | "@testing-library/react": "^13.4.0",
17 | "@testing-library/user-event": "^13.5.0",
18 | "@types/three": "^0.139.0",
19 | "@types/webgi": "https://storage.googleapis.com/dist.pixotronics.com/webgi/runtime/bundle-types-0.5.5.tgz",
20 | "gsap": "^3.11.4",
21 | "postcss-flexbugs-fixes": "^5.0.2",
22 | "postcss-normalize": "^10.0.1",
23 | "postcss-preset-env": "^8.0.1",
24 | "web-vitals": "^2.1.4",
25 | "webgi": "https://storage.googleapis.com/dist.pixotronics.com/webgi/runtime/bundle-0.5.8.tgz"
26 | },
27 | "devDependencies": {
28 | "@types/react": "^18.0.27",
29 | "@types/react-dom": "^18.0.10",
30 | "@vitejs/plugin-react": "^3.1.0",
31 | "vite": "^4.1.0",
32 | "@types/three": "^0.139.0",
33 | "@types/webgi": "https://storage.googleapis.com/dist.pixotronics.com/webgi/runtime/bundle-types-0.5.5.tgz",
34 | "cross-env": "^7.0.3",
35 | "webgi": "https://storage.googleapis.com/dist.pixotronics.com/webgi/runtime/bundle-0.5.5.tgz"
36 | }
37 | }
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/utils/scroll-animation.js:
--------------------------------------------------------------------------------
1 | import gsap from "gsap";
2 | export const scrollAnimation = (position, target, onUpdate) => {
3 | const tl = gsap.timeline();
4 | tl.to(position, {
5 | x: -3.38,
6 | y: -10.74,
7 | z: -5.93,
8 | scrollTrigger: {
9 | trigger: ".sound-section",
10 | start: "top bottom",
11 | end: "top top",
12 | scrub: 2,
13 | immediateRender: false,
14 | },
15 | onUpdate,
16 | })
17 | .to(target, {
18 | x: 1.52,
19 | y: 0.77,
20 | z: -1.08,
21 | scrollTrigger: {
22 | trigger: ".sound-section",
23 | start: "top bottom",
24 | end: "top top",
25 | scrub: 2,
26 | immediateRender: false,
27 | },
28 | onUpdate,
29 | })
30 | .to(".jumbotron-section", {
31 | opacity: 0,
32 | scrollTrigger: {
33 | trigger: ".sound-section",
34 | start: "top bottom",
35 | end: "top top",
36 | scrub: 2,
37 | immediateRender: false,
38 | },
39 | onUpdate,
40 | })
41 | .to(".sound-section-content", {
42 | opacity: 1,
43 | scrollTrigger: {
44 | trigger: ".sound-section",
45 | start: "top bottom",
46 | end: "top top",
47 | scrub: 2,
48 | immediateRender: false,
49 | },
50 | onUpdate,
51 | })
52 | .to(position, {
53 | x: 1.56,
54 | y: 5.0,
55 | z: 0.011,
56 | scrollTrigger: {
57 | trigger: ".display-section",
58 | start: "top bottom",
59 | end: "top top",
60 | scrub: 2,
61 | immediateRender: false,
62 | },
63 | onUpdate,
64 | })
65 | .to(target, {
66 | x: -0.55,
67 | y: 0.32,
68 | z: 0.0,
69 | scrollTrigger: {
70 | trigger: ".display-section",
71 | start: "top bottom",
72 | end: "top top",
73 | scrub: 2,
74 | immediateRender: false,
75 | },
76 | onUpdate,
77 | })
78 | .to(".display-section", {
79 | opacity: 1,
80 | scrollTrigger: {
81 | trigger: ".display-section",
82 | start: "top bottom",
83 | end: "top top",
84 | scrub: 2,
85 | immediateRender: false,
86 | },
87 | onUpdate,
88 | });
89 | };
90 |
--------------------------------------------------------------------------------
/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/WebGiViewer.jsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef, useCallback, useImperativeHandle } from "react";
2 | import {
3 | ViewerApp,
4 | AssetManagerPlugin,
5 | GBufferPlugin,
6 | ProgressivePlugin,
7 | TonemapPlugin,
8 | SSRPlugin,
9 | SSAOPlugin,
10 | BloomPlugin,
11 | GammaCorrectionPlugin,
12 | mobileAndTabletCheck,
13 | } from "webgi";
14 | import gsap from "gsap";
15 | import { ScrollTrigger } from "gsap/ScrollTrigger";
16 | import { scrollAnimation } from "../utils/scroll-animation";
17 |
18 | gsap.registerPlugin(ScrollTrigger);
19 |
20 | const WebGiViewer = forwardRef((props, ref) => {
21 | const canvasRef = React.useRef(null);
22 | const [viewerRef, setViewerRef] = React.useState(null);
23 | const [targetRef, setTargetRef] = React.useState(null);
24 | const [cameraRef, setCameraRef] = React.useState(null);
25 | const [positionRef, setPositionRef] = React.useState(null);
26 | const canvasContainerRef = React.useRef(null);
27 | const [prevMode, setPrevMode] = React.useState(false);
28 | useImperativeHandle(ref, () => ({
29 | triggerPreview() {
30 | setPrevMode(true);
31 | canvasContainerRef.current.style.pointerEvents = "all";
32 | props.contentRef.current.style.opacity = "0";
33 | gsap.to(positionRef, {
34 | x: 13.04,
35 | y: -2.01,
36 | z: 2.29,
37 | duration: 2,
38 | onUpdate: () => {
39 | viewerRef.setDirty();
40 | cameraRef.positionTargetUpdated(true);
41 | },
42 | });
43 |
44 | gsap.to(targetRef, {
45 | x: 0.11,
46 | y: 0.0,
47 | z: 0.0,
48 | duration: 2,
49 | });
50 | viewerRef.scene.activeCamera.setCameraOptions({ controlsEnabled: true });
51 | },
52 | }));
53 |
54 | const memScrollAnimation = React.useCallback((position, target, onUpdate) => {
55 | if (position && target && onUpdate)
56 | scrollAnimation(position, target, onUpdate);
57 | }, []);
58 |
59 | /**
60 | * Load model
61 | */
62 | const setupViewer = React.useCallback(async () => {
63 | const viewer = new ViewerApp({
64 | canvas: canvasRef.current,
65 | });
66 |
67 | setViewerRef(viewer);
68 | const manager = await viewer.addPlugin(AssetManagerPlugin);
69 |
70 | const camera = viewer.scene.activeCamera;
71 | const position = camera.position;
72 | const target = camera.target;
73 |
74 | setCameraRef(camera);
75 | setPositionRef(positionRef);
76 | setTargetRef(target);
77 | // Add plugins individually.
78 | await viewer.addPlugin(GBufferPlugin);
79 | await viewer.addPlugin(new ProgressivePlugin(32));
80 | await viewer.addPlugin(new TonemapPlugin(true));
81 | await viewer.addPlugin(GammaCorrectionPlugin);
82 | await viewer.addPlugin(SSRPlugin);
83 | await viewer.addPlugin(SSAOPlugin);
84 | await viewer.addPlugin(BloomPlugin);
85 |
86 | // This must be called once after all plugins are added.
87 | viewer.renderer.refreshPipeline();
88 |
89 | await manager.addFromPath("scene-black.glb");
90 |
91 | viewer.getPlugin(TonemapPlugin).config.clipBackground = true;
92 | viewer.scene.activeCamera.setCameraOptions({ controlsEnabled: false });
93 | window.scrollTo(0, 0);
94 |
95 | let needsUpdate = true;
96 | const onUpdate = () => {
97 | needsUpdate = true;
98 | viewer.setDirty();
99 | };
100 | viewer.addEventListener("preFrame", () => {
101 | if (needsUpdate) {
102 | camera.positionTargetUpdated(true);
103 | needsUpdate = false;
104 | }
105 | });
106 |
107 | memScrollAnimation(position, target, onUpdate);
108 | }, []);
109 |
110 | /**
111 | * Call the model
112 | */
113 | React.useEffect(() => {
114 | setupViewer();
115 | }, []);
116 |
117 | const handleExit = useCallback(() => {
118 | canvasContainerRef.current.style.pointerEvents = "none";
119 | props.contentRef.current.style.opacity = "1";
120 | viewerRef.scene.activeCamera.setCameraOptions({ controlsEnabled: false });
121 | setPrevMode(false);
122 |
123 | gsap.to(positionRef, {
124 | x: 1.56,
125 | y: 5.0,
126 | z: 0.011,
127 | scrollTrigger: {
128 | trigger: ".display-section",
129 | start: "top bottom",
130 | end: "top top",
131 | scrub: 2,
132 | immediateRender: false,
133 | },
134 | onUpdate: () => {
135 | viewerRef.setDirty();
136 | cameraRef.positionTargetUpdated(true);
137 | },
138 | });
139 | gsap.to(targetRef, {
140 | x: -0.55,
141 | y: 0.32,
142 | z: 0.0,
143 | scrollTrigger: {
144 | trigger: ".display-section",
145 | start: "top bottom",
146 | end: "top top",
147 | scrub: 2,
148 | immediateRender: false,
149 | },
150 | });
151 | }, [canvasContainerRef, viewerRef, positionRef, cameraRef, targetRef]);
152 |
153 | return (
154 |
155 |
156 | {prevMode && (
157 |
160 | )}
161 |
162 | );
163 | });
164 |
165 | export default WebGiViewer;
166 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.cdnfonts.com/css/sf-pro-display");
2 |
3 | body {
4 | margin: 0;
5 | font-family: "SF Pro Display", SF Pro Icons, Helvetica Neue, Helvetica, Arial,
6 | sans-serif;
7 | -webkit-font-smoothing: antialiased;
8 | -moz-osx-font-smoothing: grayscale;
9 | background-color: #000;
10 | color: #f5f5f7;
11 | }
12 |
13 | code {
14 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
15 | monospace;
16 | }
17 |
18 | body::-webkit-scrollbar-track {
19 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
20 | border-radius: 10px;
21 | background-color: #f5f5f5;
22 | }
23 |
24 | body::-webkit-scrollbar {
25 | width: 12px;
26 | background-color: #aaaaaa;
27 | }
28 |
29 | body::-webkit-scrollbar-thumb {
30 | border-radius: 10px;
31 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
32 | background-color: #555;
33 | }
34 |
35 | .App #content {
36 | transition-duration: 0.3s;
37 | }
38 |
39 | #webgi-canvas {
40 | width: 100%;
41 | height: 100%;
42 | background: transparent;
43 | }
44 |
45 | #webgi-canvas-container {
46 | width: 100vw;
47 | height: 100vh;
48 | position: fixed;
49 | display: flex;
50 | justify-content: flex-end;
51 | flex-direction: column;
52 | align-items: center;
53 | top: 0;
54 | pointer-events: none;
55 | min-height: 831px;
56 | background: transparent;
57 | }
58 |
59 | #webgi-canvas-container .button {
60 | background: #0071e3;
61 | color: #fff;
62 | cursor: pointer;
63 | text-align: center;
64 | white-space: nowrap;
65 | font-size: 17px;
66 | font-weight: 400;
67 | min-width: 28px;
68 | padding: 8px 16px;
69 | border-radius: 980px;
70 | position: absolute;
71 | top: 30px;
72 | border: none;
73 | z-index: 1;
74 | transition-duration: 0.3s;
75 | }
76 |
77 | .display-section.wrapper {
78 | margin-left: auto;
79 | margin-right: auto;
80 | max-width: 980px;
81 | width: 100%;
82 | display: flex;
83 | align-items: center;
84 | flex-direction: column;
85 | padding: 50px 0 400px 0;
86 | height: 100vh;
87 | box-sizing: border-box;
88 | opacity: 0;
89 | position: relative;
90 | }
91 |
92 | .display-section .title {
93 | color: #86868b;
94 | font-size: 17px;
95 | font-weight: 400;
96 | letter-spacing: -0.022em;
97 | margin-bottom: 0;
98 | }
99 |
100 | .display-section .text {
101 | display: inline-block;
102 | color: transparent;
103 | background-image: linear-gradient(180deg, #ffb6ff, #b344ff);
104 | -webkit-background-clip: text;
105 | background-clip: text;
106 | padding-top: 0.5px;
107 | margin-top: 16px;
108 | font-size: 48px;
109 | font-weight: 600;
110 | margin-bottom: 18px;
111 | }
112 |
113 | .display-section .description {
114 | font-size: 21px;
115 | font-weight: 400;
116 | }
117 |
118 | .display-section .button {
119 | background: #0071e3;
120 | color: #fff;
121 | cursor: pointer;
122 | display: inline-block;
123 | text-align: center;
124 | white-space: nowrap;
125 | font-size: 17px;
126 | font-weight: 400;
127 | min-width: 28px;
128 | padding: 8px 16px;
129 | border-radius: 980px;
130 | margin: 15px;
131 | }
132 |
133 | .display-section .back-button {
134 | background: white;
135 | color: black;
136 | border: none;
137 | border-radius: 50px;
138 | padding: 10px 30px;
139 | font-size: 0.6rem;
140 | cursor: pointer;
141 | transition: all 0.8s ease;
142 | position: fixed;
143 | bottom: 10px;
144 | right: 10px;
145 | }
146 |
147 | nav.nav-wrapper {
148 | margin: 0;
149 | width: 100%;
150 | min-width: 320px;
151 | height: 48px;
152 | max-height: 44px;
153 | font-size: 17px;
154 | background-color: #f2f2f2;
155 | }
156 |
157 | nav .nav-content {
158 | margin: 0 auto;
159 | box-sizing: border-box;
160 | width: 100%;
161 | max-width: 1024px;
162 | padding: 0 22px;
163 | }
164 |
165 | nav .list-styled {
166 | cursor: default;
167 | margin: 0 -9px;
168 | width: auto;
169 | height: 44px;
170 | display: flex;
171 | justify-content: space-between;
172 | list-style: none;
173 | }
174 |
175 | nav .link-styled {
176 | font-size: 12px;
177 | font-weight: 400;
178 | letter-spacing: -0.01em;
179 | line-height: 1;
180 | display: flex;
181 | align-items: center;
182 | justify-content: center;
183 | height: 44px;
184 | color: #000000cc;
185 | }
186 |
187 | .jumbotron-section.wrapper {
188 | margin-left: auto;
189 | margin-right: auto;
190 | max-width: 980px;
191 | width: 100%;
192 | box-sizing: border-box;
193 | height: calc(100vh - 40px);
194 | display: flex;
195 | align-items: center;
196 | flex-direction: column;
197 | padding-top: 60px;
198 | position: relative;
199 | z-index: 1;
200 | min-height: 831px;
201 | }
202 |
203 | .jumbotron-section .title {
204 | color: #86868b;
205 | font-size: 17px;
206 | font-weight: 400;
207 | letter-spacing: -0.022em;
208 | }
209 |
210 | .jumbotron-section .logo {
211 | width: 140px;
212 | }
213 |
214 | .jumbotron-section .text {
215 | display: inline-block;
216 | color: transparent;
217 | background-image: linear-gradient(180deg, #ffb6ff, #b344ff);
218 | -webkit-background-clip: text;
219 | background-clip: text;
220 | padding-top: 0.5px;
221 | margin-top: 16px;
222 | font-size: 48px;
223 | font-weight: 600;
224 | margin-bottom: 18px;
225 | }
226 |
227 | .jumbotron-section .description {
228 | font-size: 21px;
229 | font-weight: 400;
230 | }
231 |
232 | .jumbotron-section .links {
233 | display: flex;
234 | justify-content: center;
235 | margin-top: 24px;
236 | align-items: center;
237 | margin-left: 0;
238 | margin-right: 0;
239 | padding-left: 0;
240 | list-style: none;
241 | }
242 |
243 | .jumbotron-section .button {
244 | background: #0071e3;
245 | color: #fff;
246 | cursor: pointer;
247 | display: inline-block;
248 | text-align: center;
249 | white-space: nowrap;
250 | font-size: 17px;
251 | font-weight: 400;
252 | min-width: 28px;
253 | padding: 8px 16px;
254 | border-radius: 980px;
255 | margin: 0 14px;
256 | }
257 |
258 | .jumbotron-section .link {
259 | text-decoration: none;
260 | color: #2997ff;
261 | font-size: 21px;
262 | font-weight: 400;
263 | margin: 0 14px;
264 | cursor: pointer;
265 | }
266 |
267 | .jumbotron-section .iphone-img {
268 | margin-right: -400px;
269 | height: 516px;
270 | position: absolute;
271 | bottom: 0;
272 | }
273 |
274 | .mobile-or-tablet .iphone-img {
275 | display: none;
276 | }
277 |
278 | @keyframes fadeOut {
279 | from {
280 | opacity: 1;
281 | }
282 | to {
283 | opacity: 0;
284 | }
285 | }
286 |
287 | .loader {
288 | position: fixed;
289 | z-index: 2;
290 | background-color: white;
291 | top: 0;
292 | left: 0;
293 | width: 100%;
294 | height: 100%;
295 | display: flex;
296 | justify-content: center;
297 | align-items: center;
298 | animation-name: fadeOut;
299 | animation-duration: 0.3s;
300 | animation-delay: 3s;
301 | animation-fill-mode: forwards;
302 | pointer-events: none;
303 | }
304 |
305 | .loader .logo {
306 | max-width: 400px;
307 | max-height: 300px;
308 | width: 100%;
309 | height: 100%;
310 | }
311 |
312 | .sound-section.wrapper {
313 | width: 100%;
314 | color: #1d1d1f;
315 | background-color: #fbfbfd;
316 | height: 100vh;
317 | }
318 |
319 | .sound-section .body {
320 | max-width: 980px;
321 | margin: 0 auto;
322 | }
323 |
324 | .sound-section .content {
325 | max-width: 490px;
326 | width: 100%;
327 | padding: 200px 0;
328 | display: flex;
329 | align-items: center;
330 | flex-direction: column;
331 | opacity: 0;
332 | }
333 |
334 | .sound-section .title {
335 | color: #1d1d1f;
336 | font-size: 17px;
337 | font-weight: 400;
338 | margin-bottom: 0;
339 | }
340 |
341 | .sound-section .text {
342 | display: inline-block;
343 | color: transparent;
344 | background-image: linear-gradient(
345 | 90deg,
346 | #1e3791 0%,
347 | #2948b1 40%,
348 | #3153c6 55%,
349 | #385fda 60%
350 | );
351 | -webkit-background-clip: text;
352 | background-clip: text;
353 | padding-top: 0.5px;
354 | margin-top: 16px;
355 | font-size: 48px;
356 | font-weight: 600;
357 | margin-bottom: 18px;
358 | }
359 |
360 | .sound-section .description {
361 | font-size: 21px;
362 | font-weight: 400;
363 | }
364 |
365 | .sound-section .links {
366 | display: flex;
367 | justify-content: center;
368 | margin-top: 24px;
369 | align-items: center;
370 | margin-left: 0;
371 | margin-right: 0;
372 | padding-left: 0;
373 | list-style: none;
374 | }
375 |
376 | .sound-section .button {
377 | background: #0071e3;
378 | color: #fff;
379 | cursor: pointer;
380 | display: inline-block;
381 | text-align: center;
382 | white-space: nowrap;
383 | font-size: 17px;
384 | font-weight: 400;
385 | min-width: 28px;
386 | padding: 8px 16px;
387 | border-radius: 980px;
388 | margin: 0 14px;
389 | border: none;
390 | }
391 |
392 | .sound-section .link {
393 | text-decoration: none;
394 | color: #2997ff;
395 | font-size: 21px;
396 | font-weight: 400;
397 | margin: 0 14px;
398 | cursor: pointer;
399 | }
400 |
401 | @media screen and (max-width: 990px) {
402 | .jumbotron-section .iphone-img,
403 | nav .link-styled {
404 | display: none;
405 | }
406 |
407 | nav .list-styled {
408 | padding-left: 0;
409 | }
410 |
411 | .jumbotron-section.wrapper,
412 | .sound-section.wrapper,
413 | .display-section.wrapper {
414 | padding-left: 20px;
415 | padding-right: 20px;
416 | box-sizing: border-box;
417 | }
418 |
419 | .jumbotron-section .description,
420 | .sound-section .description,
421 | .display-section .description {
422 | font-size: 14px;
423 | }
424 |
425 | .jumbotron-section.wrapper,
426 | .sound-section .content,
427 | .display-section.wrapper {
428 | padding-top: 20px;
429 | }
430 |
431 | #webgi-canvas-container,
432 | .jumbotron-section.wrapper {
433 | min-height: 746px;
434 | height: 100vh;
435 | }
436 |
437 | .sound-section.wrapper {
438 | height: 100vh;
439 | }
440 |
441 | .sound-section .content {
442 | max-width: 100%;
443 | }
444 | }
445 |
--------------------------------------------------------------------------------