├── 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 | 2 | 4 | -------------------------------------------------------------------------------- /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 | 2 | 4 | -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /src/assets/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /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 | iPhone 14 Pro Max 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 | HoldingIphone 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 | --------------------------------------------------------------------------------