|
Server IP : 217.21.85.138 / Your IP : 216.73.216.103 Web Server : LiteSpeed System : Linux in-mum-web906.main-hosting.eu 4.18.0-553.37.1.lve.el8.x86_64 #1 SMP Mon Feb 10 22:45:17 UTC 2025 x86_64 User : u915722082 ( 915722082) PHP Version : 7.4.33 Disable Function : system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail MySQL : OFF | cURL : ON | WGET : ON | Perl : OFF | Python : OFF Directory (0755) : /home/u915722082/.nvm/../public_html/brandessential/ |
| [ Home ] | [ C0mmand ] | [ Upload File ] |
|---|
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Metas -->
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1"
/>
<meta
name="keywords"
content=""
/>
<meta
name="description"
content=""
/>
<meta name="author" content="" />
<!-- Title -->
<title>BRAND ESSENTIALS</title>
<!-- Favicon -->
<!-- <link rel="shortcut icon" href="assets/imgs/favicon.ico" /> -->
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link
href="https://fonts.googleapis.com/css2?family=Six+Caps&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.min.css">
<link rel="stylesheet" href="./common/css/plugins.css" />
<!-- Core Style Css -->
<link rel="stylesheet" href="./common/css/common_style.css" />
<link rel="stylesheet" href="assets/css/home8-style.css" />
<link rel="stylesheet" href="assets/css/responsive.css" />
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
/* background: url('./assets/imgs/MOCKUP-03.jpg'); */
/* background-color: #121212; */
color: #ffffff;
line-height: 1.6;
/* overflow-x: hidden; */
}
.body-container {
position: relative;
width: 100%;
}
.body-lines {
position: fixed; /* Fixed position to stay on screen */
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1; /* Above background but below content */
pointer-events: none; /* Don't interfere with clicks */
}
.body-container .body-line {
position: absolute;
top: 0;
bottom: 0;
width: 0;
border-left: solid 1px;
left: 50%;
right: initial;
border-color: #232323 !important;
z-index: 1;
}
.body-container .body-line.body-line-l1 {
margin-left: -584px;
}
.body-container .body-line.body-line-l2 {
margin-left: -170px;
}
.body-container .body-line.body-line-r1 {
margin-left: 250px;
}
.body-container .body-line.body-line-r2 {
margin-left: 640px;
}
.breadcrumb {
font-size: 48px;
/* color: #999; */
margin-bottom: 10px;
}
/* .breadcrumb span {
color: #333;
} */
.description {
color: #666;
font-size: 16px;
line-height: 1.5;
margin-bottom: 30px;
}
.categories {
display: flex;
gap: 15px;
margin-bottom: 30px;
flex-wrap: wrap;
}
.category-item {
/* background: #ebebeb; */
border-radius: 12px;
padding: 10px 20px;
font-size: 14px;
display: flex;
background: rgba(255, 255, 255, 0.10);
backdrop-filter: blur(4px);
align-items: center;
gap: 12px;
cursor: pointer;
transition: all 0.3s ease;
border: 1px solid #232323;
}
.category-item:hover {
transform: translateY(-2px);
}
.category-item.active {
border-color: #232323;
/* background: #f8f9fa; */
}
.category-item.active span{
color: #0f47ff;
}
.category-icon {
width: 40px;
height: 40px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
color: #ebebeb;
}
.category-icon img{
border-radius: 5px;
}
.shop-container {
display: flex;
gap: 0;
align-items: flex-start;
transition: gap 0.3s cubic-bezier(.12,.06,.2,1);
}
.shop-container.has-sidebar {
gap: 24px;
}
.filter-sidebar {
width: 0;
min-width: 0;
/* background: #0f47ff; */
border-radius: 12px;
background: rgba(255, 255, 255, 0.10);
backdrop-filter: blur(4px);
padding: 0;
/* box-shadow: 0 2px 10px rgba(0,0,0,0.1); */
position: sticky;
top: 20px;
height: fit-content;
max-height: calc(100vh - 40px);
overflow-y: auto;
transition: all 0.3s cubic-bezier(.12,.06,.2,1);
opacity: 0;
visibility: hidden;
}
.filter-sidebar.show {
width: calc(20% - 12px);
min-width: 280px;
padding: 15px;
opacity: 1;
visibility: visible;
}
.filter-controls {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
}
.filter-btn {
background: #ebebeb;
border: 1px solid #ddd;
border-radius: 8px;
padding: 5px 10px;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
transition: all 0.3s ease;
}
.filter-btn:hover {
background: #f8f9fa;
border-color: #ccc;
}
.filter-btn.active {
background: #333;
color: #ebebeb;
border-color: #333;
}
.results-count {
color: #666;
font-size: 14px;
}
.products-container {
flex: 1;
transition: all 0.3s cubic-bezier(.12,.06,.2,1);
}
.products-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 20px;
margin-bottom: 40px;
}
.product-card {
/* Glassmorphism Properties */
/* background: rgba(255, 255, 255, 0.10);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12); */
/* Card Properties */
overflow: hidden;
/* height: 500px; */
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
cursor: pointer;
position: relative;
z-index: 1;
}
.product-card:hover {
transform: translateY(-10px);
}
.product-card.hidden {
display: none;
}
.product-image {
width: 100%;
/* height: 400px; */
display: flex;
align-items: center;
justify-content: center;
border-radius: 16px;
font-size: 48px;
color: #666;
position: relative;
overflow: hidden;
}
.product-image img {
/* height: 400px; */
height: 300px;
width: 100%;
object-fit: cover;
}
/* Enhanced Cart Icon with Glassmorphism */
.cart-icon {
position: absolute;
top: 15px;
right: 15px;
width: 45px;
height: 45px;
background:#232323;
/* background-color: #0f47ff; */
/* border: 1px solid rgba(255, 255, 255, 0.3); */
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transform: translateY(-10px) scale(0.8);
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
cursor: pointer;
z-index: 10;
}
.cart-icon i{
font-size: 16px;
color: #fff;
}
.product-card:hover .cart-icon {
opacity: 1;
transform: translateY(0) scale(1);
}
.cart-icon:hover {
background: rgba(51, 51, 51, 0.8);
backdrop-filter: blur(15px);
transform: translateY(-3px) scale(1.1);
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3);
border-color: rgba(255, 255, 255, 0.4);
}
.cart-icon:hover svg {
stroke: #fff;
}
.cart-icon svg {
width: 22px;
height: 22px;
stroke: #fff;
stroke-width: 2;
transition: all 0.3s ease;
}
/* Animated Cart Icon */
.cart-icon:active {
transform: translateY(0) scale(0.95);
}
/* Add to Cart Animation */
.cart-icon.added {
background: rgba(76, 175, 80, 0.8);
backdrop-filter: blur(15px);
border-color: rgba(76, 175, 80, 0.6);
}
.cart-icon.added svg {
stroke: #fff;
}
/* Enhanced Pulse Animation */
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.4);
}
70% {
box-shadow: 0 0 0 15px rgba(255, 255, 255, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
}
}
.cart-icon:hover {
animation: pulse 2s infinite;
}
/* Enhanced Product Info with Glassmorphism */
.product-info {
padding: 20px;
/* background: rgba(255, 255, 255, 0.05); */
/* backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px); */
/* border-top: 1px solid rgba(255, 255, 255, 0.2); */
position: relative;
}
.product-brand {
font-size: 12px;
color: rgba(102, 102, 102, 0.9);
margin-bottom: 5px;
text-transform: uppercase;
letter-spacing: 0.5px;
font-weight: 500;
}
.product-title {
font-size: 16px;
font-weight: 600;
color: #fff;
margin-bottom: 10px;
line-height: 1.4;
}
.product-price {
font-size: 18px;
font-weight: 700;
color: rgba(51, 51, 51, 0.9);
}
/* Optional: Add a subtle glow effect */
/* .product-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg,
rgba(255, 255, 255, 0.1) 0%,
rgba(255, 255, 255, 0.05) 50%,
rgba(255, 255, 255, 0.1) 100%);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
border-radius: 16px;
} */
.product-card:hover::before {
opacity: 1;
}
/* For better glassmorphism, ensure parent container has a background */
/* You might want to add this to your container/body */
.product-container {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
/* OR use an image background */
/* background-image: url('your-background-image.jpg'); */
padding: 20px;
min-height: 100vh;
}
.filter-section {
margin-bottom: 25px;
}
.filter-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 15px;
display: flex;
color: #fff;
align-items: center;
justify-content: space-between;
cursor: pointer;
}
.filter-title span{
font-size: 12px;
}
.filter-options {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.filter-option {
/* background: #f8f9fa;
border: 1px solid #121212; */
border-radius: 6px;
padding: 8px 15px;
color: #fff;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease;
}
.filter-option.selected {
border:1px solid #e9ecef;
color: #0d45ff;
/* border-color: #333; */
}
.close-filters {
position: absolute;
right: 15px;
top: 15px;
background: none;
border: none;
font-size: 20px;
cursor: pointer;
color: #666;
padding: 5px;
border-radius: 4px;
transition: all 0.3s ease;
}
.close-filters:hover {
background: #f8f9fa;
color: #333;
}
.no-products {
text-align: center;
padding: 60px 20px;
color: #666;
font-size: 18px;
}
/* Responsive adjustments */
@media (max-width: 1200px) {
.products-grid {
grid-template-columns: repeat(2, 1fr);
}
.filter-sidebar.show {
min-width: 250px;
}
}
@media (max-width: 1024px) {
.shop-container {
flex-direction: column;
gap: 20px;
}
.filter-sidebar {
position: relative;
width: 100%;
min-width: 100%;
top: 0;
max-height: none;
}
.filter-sidebar.show {
width: 100%;
min-width: 100%;
}
}
@media (max-width: 768px) {
.categories {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.products-grid {
grid-template-columns: 1fr;
gap: 15px;
}
.filter-controls {
flex-direction: column;
gap: 15px;
align-items: stretch;
}
}
/* Popup Styles */
.popup-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
.popup-overlay.active {
opacity: 1;
visibility: visible;
}
.popup-content {
/* background: rgba(255, 255, 255, 0.10);
backdrop-filter: blur(4px); */
background-color: #232323;
border-radius: 20px;
width: 100%;
max-width: 1000px;
max-height: 90vh;
overflow-y: auto;
display: flex;
transform: scale(0.8);
transition: transform 0.3s ease;
}
.popup-overlay.active .popup-content {
transform: scale(1);
}
.popup-left {
flex: 1;
padding: 30px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.10);
backdrop-filter: blur(4px);
border-radius: 20px 0 0 20px;
}
.popup-image {
width: 100%;
max-width: 350px;
height: 300px;
border-radius: 15px;
overflow: hidden;
margin-bottom: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
.popup-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.popup-product-info {
text-align: center;
}
.popup-product-brand {
color: #fff;
font-size: 1rem;
font-weight: 600;
margin-bottom: 10px;
}
.popup-product-title {
font-size: 1.5rem;
font-weight: 600;
color: #fff;
}
.popup-right {
flex: 1;
padding: 30px;
}
.popup-close {
position: absolute;
top: 20px;
right: 20px;
/* background: #000; */
background: rgba(255, 255, 255, 0.10);
backdrop-filter: blur(4px);
color: white;
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 1.2rem;
transition: all 0.3s ease;
}
.popup-close:hover {
background: #000;
transform: scale(1.1);
}
.form-title {
font-size: 22px;
color: #fff;
margin-bottom: 20px;
text-align: center;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 400;
color: #fff;
font-size: 16px;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 7px 7px;
border:1px solid #373737;
background: none;
border-radius: 10px;
color: #fff;
font-size: 1rem;
transition: all 0.3s ease;
}
.form-group input:focus,
.form-group textarea:focus {
outline: none;
border-color: #0d45ff;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.form-group textarea {
height: 100px;
resize: vertical;
}
.submit-btn {
width: 100%;
padding: 7px 7px;
background: #0d45ff;
color: white;
border: none;
border-radius: 10px;
font-size: 19px;
font-weight: 400;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.submit-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
}
.submit-btn:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.loading-spinner {
display: none;
width: 20px;
height: 20px;
border: 2px solid #ffffff;
border-top: 2px solid transparent;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-right: 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.message {
padding: 15px;
border-radius: 10px;
margin-bottom: 20px;
text-align: center;
font-weight: 600;
display: none;
}
.message.success {
background: none;
color: #fff;
/* border: 1px solid #c3e6cb; */
}
.message.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
</style>
</head>
<body>
<div class="preloader-wrap" id="preloader">
<div class="preloader-content">
<div class="logo-wrap">
BRAND ESSENTIALS
<img src="assets/imgs/r.svg" alt="Logo">
</div>
<div class="preloader-bar-wrap">
<div class="preloader-bar"></div>
</div>
<!-- <div class="loading-text">Loading...</div> -->
</div>
</div>
<script>
// Hide preloader function
function hidePreloader() {
const preloader = document.getElementById('preloader');
preloader.classList.add('fade-out');
setTimeout(() => {
preloader.style.display = 'none';
document.body.style.overflow = 'auto';
}, 500);
}
setTimeout(hidePreloader, 4000);
</script>
<div class="cursor"></div>
<!-- <div class="progress-wrap cursor-pointer">
<svg
class="progress-circle svg-content"
width="100%"
height="100%"
viewBox="-1 -1 102 102"
>
<path d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98" />
</svg>
</div> -->
<div class="body-container">
<div class="body-lines">
<div class="body-line body-line-l1"></div>
<div class="body-line body-line-l2"></div>
<div class="body-line body-line-r1"></div>
<div class="body-line body-line-r2"></div>
</div>
<!-- Top navigation bar -->
<nav class="top-nav">
<div>
<a href="#" class="logo">BE</a>
</div>
<div class="desktop-only">
<a href="#">Work</a>
</div>
<div class="desktop-only">
<a href="#">Services</a>
</div>
<div class="desktop-only" id="aboutMenu">
<a href="#">About</a>
</div>
<div class="desktop-only">
<a href="#">Testimonials</a>
</div>
<div class="desktop-only">
<a href="#">Connect</a>
</div>
<!-- Mobile toggler button -->
<button class="mobile-toggler" id="mobileToggler">
<span class="toggler-icon"></span>
<span class="toggler-icon"></span>
<span class="toggler-icon"></span>
</button>
</nav>
<div class="sidebar" id="sidebar">
<button class="sidebar-close" id="sidebarClose">×</button>
<div class="sidebar-links">
<div>
<a href="#">Work</a>
</div>
<div>
<a href="#">Services</a>
</div>
<div>
<a href="#">About</a>
</div>
<div>
<a href="#">Testimonials</a>
</div>
<div>
<a href="#">Connect</a>
</div>
</div>
</div>
<style>
.shop-section .container{
max-width: 1850px ;
}
.category-item span{
color: #fff;
}
</style>
<div class="shop-section pb-150px">
<div class="container">
<div class="shop-top-area pt-150px pb-px">
<div class="header">
<div class="breadcrumb">All › <span> Design Assets</span></div>
<div class="description">Explore our complete design collection. Featuring premium templates and creative assets to elevate your brand in any environment.</div>
</div>
<div class="categories">
<div class="category-item active" data-category="all">
<span>All Products</span>
</div>
<div class="category-item" data-category="banners">
<div class="category-icon banners">
<img src="assets/imgs/BE-01.jpg" alt="Banners">
</div>
<span>Web Banners</span>
</div>
<div class="category-item" data-category="mockups">
<div class="category-icon mockups">
<img src="assets/imgs/BE-01.jpg" alt="Mockups">
</div>
<span>Mockups</span>
</div>
<div class="category-item" data-category="posters">
<div class="category-icon posters">
<img src="assets/imgs/BE-01.jpg" alt="Posters">
</div>
<span>Posters</span>
</div>
<!-- <div class="category-item" data-category="social">
<div class="category-icon social">
<img src="assets/imgs/BE-01.jpg" alt="Social">
</div>
<span>Social Media</span>
</div>
<div class="category-item" data-category="websites">
<div class="category-icon websites">
<img src="assets/imgs/BE-01.jpg" alt="Websites">
</div>
<span>Website Sales</span>
</div> -->
</div>
</div>
</div>
<div class="container">
<div class="shop-container">
<div class="filter-sidebar" id="filterSidebar">
<div class="filter-section">
<div class="filter-title">Sort By <span class="icon ml-10">
<i class="fa-solid fa-chevron-right"></i>
</span></div>
<div class="filter-options">
<div class="filter-option selected">Featured</div>
<div class="filter-option">Price: Low to High</div>
<div class="filter-option">Price: High to Low</div>
<div class="filter-option">Newest</div>
<div class="filter-option">Best Selling</div>
</div>
</div>
<div class="filter-section">
<div class="filter-title">Style <span class="icon ml-10">
<i class="fa-solid fa-chevron-right"></i>
</span></div>
<div class="filter-options">
<div class="filter-option">Modern</div>
<div class="filter-option">Minimalist</div>
<div class="filter-option">Creative</div>
<div class="filter-option">Professional</div>
<div class="filter-option">Colorful</div>
</div>
</div>
<div class="filter-section">
<div class="filter-title">Color <span class="icon ml-10">
<i class="fa-solid fa-chevron-right"></i>
</span></div>
<div class="filter-options">
<div class="filter-option">Blue</div>
<div class="filter-option">Red</div>
<div class="filter-option">Green</div>
<div class="filter-option">Purple</div>
<div class="filter-option">Orange</div>
<div class="filter-option">Black & White</div>
</div>
</div>
<div class="filter-section">
<div class="filter-title">Format <span class="icon ml-10">
<i class="fa-solid fa-chevron-right"></i>
</span></div>
<div class="filter-options">
<div class="filter-option">PSD</div>
<div class="filter-option">AI</div>
<div class="filter-option">PNG</div>
<div class="filter-option">JPG</div>
<div class="filter-option">SVG</div>
</div>
</div>
</div>
<style>
.filter-options {
display: none;
transition: all 0.3s ease;
}
.filter-options.active {
display: block;
}
.icon i.rotate {
transform: rotate(90deg);
transition: transform 0.3s ease;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
const sections = document.querySelectorAll('.filter-section');
sections.forEach((section, index) => {
const title = section.querySelector('.filter-title');
const options = section.querySelector('.filter-options');
const icon = section.querySelector('.icon i');
// Initially activate the first section
if (index === 0) {
options.classList.add('active');
icon.classList.add('rotate');
}
title.addEventListener('click', () => {
// Close all other sections
sections.forEach(s => {
const otherOptions = s.querySelector('.filter-options');
const otherIcon = s.querySelector('.icon i');
if (s !== section) {
otherOptions.classList.remove('active');
otherIcon.classList.remove('rotate');
}
});
// Toggle current section
options.classList.toggle('active');
icon.classList.toggle('rotate');
});
});
});
</script>
<div class="products-container" id="productsContainer">
<div class="filter-controls">
<button class="filter-btn" id="filterToggle">
<svg width="32" height="32" viewBox="0 0 32 33" fill="none" class="group" xmlns="http://www.w3.org/2000/svg">
<path d="M7 13.999H24" stroke="#151516" stroke-linecap="round"></path>
<circle cx="12" cy="13.999" r="2.5" class="transition-all ease-ease-1" fill="#F3EEEA" stroke="#151516"></circle>
<path d="M7 20.999H24" stroke="#151516" stroke-linecap="round"></path>
<circle cx="19" cy="20.999" r="2.5" class="transition-all ease-ease-1" fill="#F3EEEA" stroke="#151516"></circle>
</svg>
</button>
<div class="results-count" id="resultsCount">15 Results</div>
</div>
<div class="products-grid" id="productsGrid">
<!-- Web Banners -->
<div class="product-card" data-category="banners" onclick="openPopup(this, 'Premium Web Banner Collection')">
<div class="product-image banner">
<img src="./assets/imgs/MOCKUP-01.jpg" alt="Banner">
<div class="cart-icon">
<!-- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<circle cx="9" cy="21" r="1"></circle>
<circle cx="20" cy="21" r="1"></circle>
<path d="m1 1 4 4 8 5 4-1h4l-1 4-8-1-4 4-4-4"></path>
</svg> -->
<i class="fa fa-shopping-bag"></i>
</div>
</div>
<div class="product-info">
<div class="product-brand">BRANDESSENTIALS</div>
<div class="product-title">Premium Web Banner Collection</div>
</div>
</div>
<div class="product-card" data-category="banners" onclick="openPopup(this, 'E-commerce Banner Set', './assets/imgs/MOCKUP-02.jpg')">
<div class="product-image banner">
<img src="./assets/imgs/MOCKUP-02.jpg" alt="Banner">
<div class="cart-icon">
<!-- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<circle cx="9" cy="21" r="1"></circle>
<circle cx="20" cy="21" r="1"></circle>
<path d="m1 1 4 4 8 5 4-1h4l-1 4-8-1-4 4-4-4"></path>
</svg> -->
<i class="fa fa-shopping-bag"></i>
</div>
</div>
<div class="product-info">
<div class="product-brand">BRANDESSENTIALS</div>
<div class="product-title">E-commerce Banner Set</div>
</div>
</div>
<div class="product-card" data-category="banners" onclick="openPopup(this, 'Corporate Banner Bundle', './assets/imgs/MOCKUP-03.jpg')">
<div class="product-image banner">
<img src="./assets/imgs/MOCKUP-03.jpg" alt="Banner">
<div class="cart-icon">
<i class="fa fa-shopping-bag"></i>
</div>
</div>
<div class="product-info">
<div class="product-brand">BRANDESSENTIALS</div>
<div class="product-title">Corporate Banner Bundle</div>
</div>
</div>
<!-- Mockups -->
<div class="product-card" data-category="mockups" onclick="openPopup(this, 'Device Mockup Bundle', './assets/imgs/MOCKUP-04.jpg')">
<div class="product-image mockups">
<img src="./assets/imgs/MOCKUP-04.jpg" alt="Mockup">
<div class="cart-icon">
<i class="fa fa-shopping-bag"></i>
</div>
</div>
<div class="product-info">
<div class="product-brand">BRANDESSENTIALS</div>
<div class="product-title">Device Mockup Bundle</div>
</div>
</div>
<div class="product-card" data-category="mockups" onclick="openPopup(this, 'App Screen Mockups', './assets/imgs/MOCKUP-01.jpg')">
<div class="product-image mockups">
<img src="./assets/imgs/MOCKUP-01.jpg" alt="Mockup">
<div class="cart-icon">
<i class="fa fa-shopping-bag"></i>
</div>
</div>
<div class="product-info">
<div class="product-brand">BRANDESSENTIALS</div>
<div class="product-title">App Screen Mockups</div>
</div>
</div>
<div class="product-card" data-category="mockups" onclick="openPopup(this, 'Brand Identity Mockups', './assets/imgs/MOCKUP-02.jpg')">
<div class="product-image mockups">
<img src="./assets/imgs/MOCKUP-02.jpg" alt="Mockup">
<div class="cart-icon">
<i class="fa fa-shopping-bag"></i>
</div>
</div>
<div class="product-info">
<div class="product-brand">BRANDESSENTIALS</div>
<div class="product-title">Brand Identity Mockups</div>
</div>
</div>
<!-- posters-->
<div class="product-card" data-category="posters" onclick="openPopup(this, 'Device Mockup Bundle', './assets/imgs/MOCKUP-04.jpg')">
<div class="product-image posters">
<img src="./assets/imgs/MOCKUP-04.jpg" alt="Mockup">
<div class="cart-icon">
<i class="fa fa-shopping-bag"></i>
</div>
</div>
<div class="product-info">
<div class="product-brand">BRANDESSENTIALS</div>
<div class="product-title">Device Mockup Bundle</div>
</div>
</div>
<div class="product-card" data-category="posters" onclick="openPopup(this, 'App Screen Mockups', './assets/imgs/MOCKUP-01.jpg')">
<div class="product-image posters">
<img src="./assets/imgs/MOCKUP-01.jpg" alt="Mockup">
<div class="cart-icon">
<i class="fa fa-shopping-bag"></i>
</div>
</div>
<div class="product-info">
<div class="product-brand">BRANDESSENTIALS</div>
<div class="product-title">App Screen Mockups</div>
</div>
</div>
<div class="product-card" data-category="posters" onclick="openPopup(this, 'Brand Identity Mockups', './assets/imgs/MOCKUP-02.jpg')">
<div class="product-image posters">
<img src="./assets/imgs/MOCKUP-02.jpg" alt="Mockup">
<div class="cart-icon">
<i class="fa fa-shopping-bag"></i>
</div>
</div>
<div class="product-info">
<div class="product-brand">BRANDESSENTIALS</div>
<div class="product-title">Brand Identity Mockups</div>
</div>
</div>
<!-- Add more products as needed -->
</div>
</div>
<!-- Popup -->
<div class="popup-overlay" id="popupOverlay">
<div class="popup-content">
<button class="popup-close" onclick="closePopup()">×</button>
<div class="popup-left">
<div class="popup-image">
<img id="popupImage" src="" alt="Product Image">
</div>
<div class="popup-product-info">
<div class="popup-product-brand">BRANDESSENTIALS</div>
<!-- <div class="popup-product-title" id="popupProductTitle"></div> -->
</div>
</div>
<div class="popup-right">
<h2 class="form-title">Get This Product</h2>
<div class="message" id="message"></div>
<form id="contactForm">
<div class="form-group">
<label for="name">Name *</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="company">Company Name</label>
<input type="text" id="company" name="company">
</div>
<div class="form-group">
<label for="subject">Subject *</label>
<input type="text" id="subject" name="subject" required>
</div>
<div class="form-group">
<label for="phone">Phone Number *</label>
<input type="tel" id="phone" name="phone" required>
</div>
<div class="form-group">
<label for="email">Email *</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="message">Message</label>
<textarea id="messageText" name="message" placeholder="Tell us about your requirements..."></textarea>
</div>
<button type="submit" class="submit-btn" id="submitBtn">
<span class="loading-spinner" id="loadingSpinner"></span>
<span id="submitText">Send Inquiry</span>
</button>
</form>
</div>
</div>
</div>
<script>
let currentProduct = '';
function openPopup(element, productTitle, imageSrc) {
currentProduct = productTitle;
// Get the actual image from the clicked card
const cardImage = element.querySelector('.product-image img');
const actualImageSrc = cardImage.src;
// Set popup content
document.getElementById('popupImage').src = actualImageSrc;
// Pre-fill subject with product name
document.getElementById('subject').value = `Inquiry about ${productTitle}`;
// Show popup
document.getElementById('popupOverlay').classList.add('active');
document.body.style.overflow = 'hidden';
}
function closePopup() {
document.getElementById('popupOverlay').classList.remove('active');
document.body.style.overflow = 'auto';
// Reset form
document.getElementById('contactForm').reset();
document.getElementById('message').style.display = 'none';
}
// Close popup when clicking outside
document.getElementById('popupOverlay').addEventListener('click', function(e) {
if (e.target === this) {
closePopup();
}
});
// Handle form submission
document.getElementById('contactForm').addEventListener('submit', function(e) {
e.preventDefault();
const submitBtn = document.getElementById('submitBtn');
const loadingSpinner = document.getElementById('loadingSpinner');
const submitText = document.getElementById('submitText');
const messageDiv = document.getElementById('message');
// Show loading state
submitBtn.disabled = true;
loadingSpinner.style.display = 'inline-block';
submitText.textContent = 'Sending...';
messageDiv.style.display = 'none';
// Collect form data
const formData = new FormData();
formData.append('name', document.getElementById('name').value);
formData.append('company', document.getElementById('company').value);
formData.append('subject', document.getElementById('subject').value);
formData.append('phone', document.getElementById('phone').value);
formData.append('email', document.getElementById('email').value);
formData.append('message', document.getElementById('messageText').value);
formData.append('product', currentProduct);
// Send to PHP script
fetch('send-enquiry.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
messageDiv.style.display = 'block';
if (data.status === 'success') {
messageDiv.className = 'message success';
messageDiv.textContent = data.message;
document.getElementById('contactForm').reset();
// Close popup after 2 seconds
setTimeout(() => {
closePopup();
}, 2000);
} else {
messageDiv.className = 'message error';
messageDiv.textContent = data.message;
}
})
.catch(error => {
console.error('Error:', error);
messageDiv.style.display = 'block';
messageDiv.className = 'message error';
messageDiv.textContent = 'An error occurred. Please try again.';
})
.finally(() => {
// Reset button state
submitBtn.disabled = false;
loadingSpinner.style.display = 'none';
submitText.textContent = 'Send Inquiry';
});
});
// Add smooth scrolling effect
document.addEventListener('DOMContentLoaded', function() {
const cards = document.querySelectorAll('.product-card');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
});
cards.forEach(card => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = 'all 0.6s ease';
observer.observe(card);
});
});
</script>
<script>
function addToCart(element, productName) {
// Prevent event bubbling
event.stopPropagation();
// Add visual feedback
element.classList.add('added');
// Show notification
const notification = document.getElementById('notification');
notification.textContent = `${productName} added to cart!`;
notification.classList.add('show');
// Reset cart icon after animation
setTimeout(() => {
element.classList.remove('added');
}, 1000);
// Hide notification
setTimeout(() => {
notification.classList.remove('show');
}, 3000);
// Here you would typically add the item to your cart array or send to backend
console.log(`Added to cart: ${productName}`);
}
</script>
</div>
</div>
</div>
<script>
// Get all necessary elements
const filterToggle = document.getElementById('filterToggle');
const filterSidebar = document.getElementById('filterSidebar');
const filterOptions = document.querySelectorAll('.filter-option');
const categoryItems = document.querySelectorAll('.category-item');
const productCards = document.querySelectorAll('.product-card');
const resultsCount = document.getElementById('resultsCount');
// Filter sidebar toggle
function toggleSidebar() {
const shopContainer = document.querySelector('.shop-container');
filterSidebar.classList.toggle('show');
filterToggle.classList.toggle('active');
shopContainer.classList.toggle('has-sidebar');
if (filterSidebar.classList.contains('show')) {
filterToggle.innerHTML = '<svg width="24" height="24" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7 7.97168L17 17.9717M17 7.97168L7 17.9717" stroke="white" stroke-width="1.00312" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
} else {
filterToggle.innerHTML = '<svg width="32" height="32" viewBox="0 0 32 33" fill="none" class="group" xmlns="http://www.w3.org/2000/svg"><path d="M7 13.999H24" stroke="#151516" stroke-linecap="round"></path><circle cx="12" cy="13.999" r="2.5" class="transition-all ease-ease-1" fill="#F3EEEA" stroke="#151516"></circle><path d="M7 20.999H24" stroke="#151516" stroke-linecap="round"></path><circle cx="19" cy="20.999" r="2.5" class="transition-all ease-ease-1" fill="#F3EEEA" stroke="#151516"></circle></svg>';
}
}
// Add event listener for filter toggle
filterToggle.addEventListener('click', toggleSidebar);
// Filter option selection for sidebar filters
filterOptions.forEach(option => {
option.addEventListener('click', function() {
const siblings = this.parentElement.querySelectorAll('.filter-option');
siblings.forEach(sibling => sibling.classList.remove('selected'));
this.classList.add('selected');
});
});
// Category filtering function
function filterProducts(category) {
let visibleCount = 0;
productCards.forEach(card => {
const cardCategory = card.getAttribute('data-category');
console.log(`Card category: ${cardCategory}, Filter: ${category}`); // Debug log
if (category === 'all' || cardCategory === category) {
card.classList.remove('hidden');
card.style.display = 'block';
visibleCount++;
} else {
card.classList.add('hidden');
card.style.display = 'none';
}
});
// Update results count
resultsCount.textContent = `${visibleCount} Results`;
// Show message if no products found
const productsGrid = document.getElementById('productsGrid');
let noProductsMessage = document.querySelector('.no-products');
if (visibleCount === 0) {
if (!noProductsMessage) {
noProductsMessage = document.createElement('div');
noProductsMessage.className = 'no-products';
noProductsMessage.textContent = 'No products found for this category.';
productsGrid.appendChild(noProductsMessage);
}
} else {
if (noProductsMessage) {
noProductsMessage.remove();
}
}
}
// Category selection event listeners
categoryItems.forEach(item => {
item.addEventListener('click', function() {
console.log('Category clicked:', this.getAttribute('data-category')); // Debug log
// Remove active class from all categories
categoryItems.forEach(cat => cat.classList.remove('active'));
// Add active class to clicked category
this.classList.add('active');
// Get the category and filter products
const category = this.getAttribute('data-category');
filterProducts(category);
});
});
// Initialize with all products visible
filterProducts('all');
</script>
<div class="footer" data-border="true">
<div class="top-section">
<div class="logo1">
<a href="index.html">BRAND <br>ESSENTIALS</a>
</div>
<div class="nav-section">
<a href="#">Work</a><br>
<a href="#">Services</a><br>
<a href="#">About</a><br>
<a href="#">Testimonials</a><br>
<a href="#" rel="noopener">Connect</a><br>
</div>
<div class="email-section">
<a href="mailto:info@BRANDESSENTIALSs.in" rel="noopener">info@BRANDESSENTIALSs.in</a>
</div>
</div>
<div class="bottom-section">
<div class="copyright">
©BE 2025
</div>
<div class="social">
<!-- <a href="#"rel="noopener">LinkedIn</a>,
<a href="#" rel="noopener">X,</a> -->
<a href="#" rel="noopener">Instagram</a>
<!-- <a href="#"rel="noopener">YouTube</a> -->
</div>
<div class="empty">
</div>
</div>
<!-- Wave animation section -->
<div class="wave-container1">
<!-- Base wave image (optional SVG background) -->
<img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%221729%22%20height%3D%221802%22%20fill%3D%22none%22%3E%3Cmask%20id%3D%22a%22%20width%3D%221729%22%20height%3D%221802%22%20x%3D%220%22%20y%3D%220%22%20maskUnits%3D%22userSpaceOnUse%22%20style%3D%22mask-type%3Aalpha%22%3E%3Cpath%20fill%3D%22%23frfrf%22%20d%3D%22M0%200h1728v1800.83H0z%22%20style%3D%22fill%3A%23d9d9d9%3Bfill%3Acolor(display-p3%20.851%20.851%20.851)%3Bfill-opacity%3A1%22%20transform%3D%22matrix(-1%200%200%201%201728.71%20.863)%22%2F%3E%3C%2Fmask%3E%3Cg%20mask%3D%22url(%23a)%22%3E%3Cg%20filter%3D%22url(%23b)%22%3E%3Cpath%20fill%3D%22%23FF7300%22%20d%3D%22M243.146%20442.489C56.421%20296.6-247.47%20322.512-376.076%20353.704l179.126%20923.906H851.931l944.119%2033.15%20265.09-728.258c5.7-7.723-39.35-65.812-265.09-236.39-282.19-213.223-705.48-75.755-838.158%2097.211-132.674%20172.966-481.339%20181.526-714.746-.834Z%22%20style%3D%22fill%3A%23ff7300%3Bfill%3A%20color(display-p3%200%200.23%201)%3Bfill-opacity%3A1%22%2F%3E%3C%2Fg%3E%3Cg%20filter%3D%22url(%23c)%22%3E%3Cpath%20stroke%3D%22red%22%20stroke-width%3D%2271%22%20d%3D%22M2061.14%20582.5c5.7-7.723-39.35-65.812-265.1-236.39-282.18-213.223-705.47-75.755-838.149%2097.211-132.674%20172.966-481.339%20181.526-714.745-.834C56.42%20296.599-247.472%20322.51-376.077%20353.701%22%20style%3D%22stroke%3Ared%3Bstroke%3A%20color(display-p3%200%200.36%201)%3Bstroke-opacity%3A1%22%2F%3E%3C%2Fg%3E%3Cg%20filter%3D%22url(%23d)%22%20opacity%3D%22.5%22%3E%3Cpath%20stroke%3D%22red%22%20stroke-width%3D%2271%22%20d%3D%22M2061.13%20531.531c5.7-7.722-39.35-65.812-265.09-236.39-282.18-213.223-705.48-75.755-838.156%2097.211-229.419%20299.09-481.34%20181.526-714.746-.834C56.412%20245.63-247.479%20271.541-376.085%20302.732%22%20style%3D%22stroke%3Ared%3Bstroke%3A%20color(display-p3%200%201%200.94)%3Bstroke-opacity%3A1%22%2F%3E%3C%2Fg%3E%3Cg%20filter%3D%22url(%23e)%22%3E%3Cpath%20fill%3D%22%23fff%22%20d%3D%22M-478.381%201420.69c0%202117.34%20655.442%201664.27%201382.846%201664.27%20727.405%200%201251.315%20143.55%201251.315-1664.27%200-267.57-589.68-484.482-1317.08-484.482-727.404%200-1317.081%20216.912-1317.081%20484.482Z%22%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%22%2F%3E%3C%2Fg%3E%3C%2Fg%3E%3Cdefs%3E%3Cfilter%20id%3D%22b%22%20width%3D%222845.68%22%20height%3D%221481.29%22%20x%3D%22-580.078%22%20y%3D%2233.467%22%20color-interpolation-filters%3D%22sRGB%22%20filterUnits%3D%22userSpaceOnUse%22%3E%3CfeFlood%20flood-opacity%3D%220%22%20result%3D%22BackgroundImageFix%22%2F%3E%3CfeBlend%20in%3D%22SourceGraphic%22%20in2%3D%22BackgroundImageFix%22%20result%3D%22shape%22%2F%3E%3CfeGaussianBlur%20result%3D%22effect1_foregroundBlur_760_56865%22%20stdDeviation%3D%22102%22%2F%3E%3C%2Ffilter%3E%3Cfilter%20id%3D%22c%22%20width%3D%222889.54%22%20height%3D%22817.69%22%20x%3D%22-588.445%22%20y%3D%22-2.023%22%20color-interpolation-filters%3D%22sRGB%22%20filterUnits%3D%22userSpaceOnUse%22%3E%3CfeFlood%20flood-opacity%3D%220%22%20result%3D%22BackgroundImageFix%22%2F%3E%3CfeBlend%20in%3D%22SourceGraphic%22%20in2%3D%22BackgroundImageFix%22%20result%3D%22shape%22%2F%3E%3CfeGaussianBlur%20result%3D%22effect1_foregroundBlur_760_56865%22%20stdDeviation%3D%22102%22%2F%3E%3C%2Ffilter%3E%3Cfilter%20id%3D%22d%22%20width%3D%222889.54%22%20height%3D%22867.63%22%20x%3D%22-588.453%22%20y%3D%22-52.992%22%20color-interpolation-filters%3D%22sRGB%22%20filterUnits%3D%22userSpaceOnUse%22%3E%3CfeFlood%20flood-opacity%3D%220%22%20result%3D%22BackgroundImageFix%22%2F%3E%3CfeBlend%20in%3D%22SourceGraphic%22%20in2%3D%22BackgroundImageFix%22%20result%3D%22shape%22%2F%3E%3CfeGaussianBlur%20result%3D%22effect1_foregroundBlur_760_56865%22%20stdDeviation%3D%22102%22%2F%3E%3C%2Ffilter%3E%3Cfilter%20id%3D%22e%22%20width%3D%223202.16%22%20height%3D%222757.44%22%20x%3D%22-762.383%22%20y%3D%22652.208%22%20color-interpolation-filters%3D%22sRGB%22%20filterUnits%3D%22userSpaceOnUse%22%3E%3CfeFlood%20flood-opacity%3D%220%22%20result%3D%22BackgroundImageFix%22%2F%3E%3CfeBlend%20in%3D%22SourceGraphic%22%20in2%3D%22BackgroundImageFix%22%20result%3D%22shape%22%2F%3E%3CfeGaussianBlur%20result%3D%22effect1_foregroundBlur_760_56865%22%20stdDeviation%3D%22142%22%2F%3E%3C%2Ffilter%3E%3C%2Fdefs%3E%3C%2Fsvg%3E"
alt="Wave design"
class="wave-base">
<!-- Canvas for wave animation -->
<canvas id="waveCanvas1" resize></canvas>
<div id="gui_container1"></div>
</div>
</div>
</div>
</div>
<!-- <div class="bottom-blur-container">
<div class="backdrop-blur-effect">
<div class="blur-layer blur-layer-1"></div>
<div class="blur-layer blur-layer-2"></div>
<div class="blur-layer blur-layer-3"></div>
<div class="blur-layer blur-layer-4"></div>
<div class="blur-layer blur-layer-5"></div>
<div class="blur-layer blur-layer-6"></div>
<div class="blur-layer blur-layer-7"></div>
<div class="blur-layer blur-layer-8"></div>
</div>
</div> -->
<div class="subscr-cover-link" id="subscrLink" style="--width: 253.156px;">
<div>
<a href="#" class="butn butn-rounded">
<div class="d-flex align-items-center">
<span class="text">
<span>
Let's get on a <strong>call</strong>
</span>
</span>
<span class="icon ml-10">
<img src="https://uithemez.com/i/hubfolio_HTML/common/imgs/icons/arrow-top-right.svg" alt="">
</span>
</div>
</a>
</div>
</div>
<script src="./common/js/lib/jquery-3.6.0.min.js"></script>
<script src="./common/js/lib/jquery-migrate-3.4.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/8.4.7/swiper-bundle.min.js"></script>
<script>
class WaveAnimation {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext('2d');
this.ratio = window.devicePixelRatio || 1;
// Keep desktop wave properties for all devices
this.waveTotal = 6;
this.baseWaveHeight = 120;
this.maxWaveHeight = 300;
this.waveSpeed = 0.20;
// Frequency properties
this.frequencyNodes = [];
this.frequencySpeed = 0.02;
this.frequencyScale = 1;
this.time = 0;
// Initialize nodes
this.nodes = this.setWaveNodes();
this.initFrequencyNodes();
// Initialize canvas
this.init();
// Start animation
this.animate();
// Handle resize with debouncing for better performance
this.resizeTimeout = null;
window.addEventListener('resize', () => {
clearTimeout(this.resizeTimeout);
this.resizeTimeout = setTimeout(() => {
this.resizeCanvasToDisplaySize();
}, 100);
});
// Handle orientation change on mobile
window.addEventListener('orientationchange', () => {
setTimeout(() => {
this.resizeCanvasToDisplaySize();
}, 100);
});
}
setWaveNodes() {
const offSetNodes = this.waveTotal + 2;
const canvasWidth = this.canvas ? this.canvas.getBoundingClientRect().width : window.innerWidth;
return [...Array(offSetNodes)].map((_, index) => [
((index - 1) * canvasWidth) / this.waveTotal,
0,
Math.random() * this.baseWaveHeight,
this.waveSpeed
]);
}
initFrequencyNodes() {
// Create frequency modulation nodes for each wave point
this.frequencyNodes = this.nodes.map((_, index) => ({
amplitude: Math.random() * 0.8 + 0.2, // Random amplitude between 0.2 and 1
frequency: Math.random() * 0.03 + 0.01, // Random frequency
phase: Math.random() * Math.PI * 2, // Random phase offset
heightMultiplier: Math.random() * 0.7 + 0.3, // Height variation
speedMultiplier: Math.random() * 0.5 + 0.5 // Speed variation
}));
}
init() {
this.sizeCanvas();
}
sizeCanvas() {
const rect = this.canvas.getBoundingClientRect();
const width = rect.width;
const height = rect.height;
// Use appropriate pixel ratio for better mobile performance
const pixelRatio = Math.min(this.ratio, window.innerWidth <= 768 ? 1.5 : 2);
if (this.canvas.width !== width * pixelRatio || this.canvas.height !== height * pixelRatio) {
this.canvas.width = width * pixelRatio;
this.canvas.height = height * pixelRatio;
this.canvas.style.width = width + 'px';
this.canvas.style.height = height + 'px';
this.ctx.scale(pixelRatio, pixelRatio);
return true;
}
return false;
}
resizeCanvasToDisplaySize() {
const rect = this.canvas.getBoundingClientRect();
const width = rect.width;
const height = rect.height;
const pixelRatio = Math.min(this.ratio, window.innerWidth <= 768 ? 1.5 : 2);
// Always update canvas size to match current container
this.canvas.width = width * pixelRatio;
this.canvas.height = height * pixelRatio;
this.canvas.style.width = width + 'px';
this.canvas.style.height = height + 'px';
this.ctx.scale(pixelRatio, pixelRatio);
// Recalculate nodes based on new width
this.nodes = this.setWaveNodes();
this.initFrequencyNodes();
return true;
}
diff(a, b) {
return (b - a) / 2 + a;
}
getFrequencyHeight(index) {
const freqNode = this.frequencyNodes[index];
if (!freqNode) return 1;
// Create complex frequency pattern
const baseFreq = Math.sin(this.time * freqNode.frequency + freqNode.phase);
const harmonicFreq = Math.sin(this.time * freqNode.frequency * 2.3 + freqNode.phase * 1.7) * 0.3;
const slowFreq = Math.sin(this.time * freqNode.frequency * 0.5 + freqNode.phase * 0.8) * 0.5;
// Combine frequencies for more organic movement
const combined = (baseFreq + harmonicFreq + slowFreq) * freqNode.amplitude;
// Create dramatic height variations (like frequency analyzer)
const heightVariation = Math.abs(combined) * freqNode.heightMultiplier;
// Add some randomness for natural feel
const randomVariation = Math.sin(this.time * 0.1 + index) * 0.2;
return Math.max(0.1, heightVariation + randomVariation + 0.3);
}
drawWave() {
const wave = this.nodes;
const ctx = this.ctx;
const canvasWidth = this.canvas.getBoundingClientRect().width;
// Dynamic gradient based on wave intensity
const avgHeight = wave.reduce((sum, node) => sum + node[1], 0) / wave.length;
const intensity = Math.min(1, avgHeight / this.maxWaveHeight);
// Create responsive gradient that works on all screen sizes
const gradient = ctx.createRadialGradient(
canvasWidth * 0.1, 0, canvasWidth * 0.5,
canvasWidth * 0.1, canvasWidth * 0.25, canvasWidth * 1.5
);
gradient.addColorStop(0.15, "#02019d");
gradient.addColorStop(0.5, "#02019d");
gradient.addColorStop(1, "#02019d");
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.moveTo(0, ctx.canvas.height / (this.ratio || 1));
// First wave node
ctx.lineTo(wave[0][0], wave[0][1]);
for (let i = 0; i < wave.length; i++) {
if (wave[i + 1]) {
ctx.quadraticCurveTo(
wave[i][0],
wave[i][1],
this.diff(wave[i][0], wave[i + 1][0]),
this.diff(wave[i][1], wave[i + 1][1])
);
} else {
// Last wave node
ctx.lineTo(wave[i][0], wave[i][1]);
ctx.lineTo(canvasWidth, ctx.canvas.height / (this.ratio || 1));
}
}
ctx.closePath();
ctx.fill();
}
draw() {
const ctx = this.ctx;
this.time += this.frequencySpeed;
const canvasWidth = this.canvas.getBoundingClientRect().width;
const canvasHeight = this.canvas.getBoundingClientRect().height;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// Update nodes with frequency-based heights
this.nodes = this.nodes.map((node, index) => {
const frequencyHeight = this.getFrequencyHeight(index);
const dynamicHeight = this.baseWaveHeight + (this.maxWaveHeight - this.baseWaveHeight) * frequencyHeight;
// Create wave motion with dynamic height
const waveMotion = (dynamicHeight / 2) * Math.sin(node[2] / 15);
// Improved base position calculation that works consistently across devices
const basePosition = canvasHeight * 0.5 - (canvasHeight * 0.45) + dynamicHeight;
return [
node[0],
waveMotion + basePosition,
node[2] + node[3] * this.frequencyNodes[index].speedMultiplier,
node[3]
];
});
this.drawWave();
}
animate() {
this.draw();
this.animationFrameId = requestAnimationFrame(() => this.animate());
}
destroy() {
if (this.animationFrameId) {
cancelAnimationFrame(this.animationFrameId);
}
clearTimeout(this.resizeTimeout);
window.removeEventListener('resize', () => this.resizeCanvasToDisplaySize());
window.removeEventListener('orientationchange', () => this.resizeCanvasToDisplaySize());
}
}
// Initialize the wave animation with the new canvas ID
const wave2 = new WaveAnimation('waveCanvas1');
</script>
<!-- GSAP -->
<script src="./common/js/gsap_lib/gsap.min.js"></script>
<script src="./common/js/gsap_lib/ScrollSmoother.min.js"></script>
<script src="./common/js/gsap_lib/ScrollSmoother.min.js"></script>
<script src="./common/js/gsap_lib/ScrollTrigger.min.js"></script>
<script src="./common/js/gsap_lib/SplitText.min.js"></script>
<!-- common scripts -->
<script src="assets/js/scripts.js"></script>
<script src="./common/js/common_scripts.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
const bodyLines = document.querySelectorAll(".body-line");
bodyLines.forEach((line) => {
// Create multiple moving dots for each line
for (let i = 0; i < 3; i++) {
createMovingDot(line);
}
// Create new dots periodically
setInterval(() => {
if (Math.random() > 0.7) {
// Randomly add new dots
createMovingDot(line);
}
}, 2000);
});
function createMovingDot(line) {
const dot = document.createElement("div");
dot.className = "moving-dot";
// Randomize animation duration between 8 and 15 seconds
const duration = 8 + Math.random() * 7;
dot.style.animationDuration = `${duration}s`;
// Randomize animation delay
const delay = Math.random() * 8;
dot.style.animationDelay = `${delay}s`;
// Slightly vary height between 12px and 20px
dot.style.height = `${12 + Math.random() * 8}px`;
// Slightly vary opacity
dot.style.opacity = 0.5 + Math.random() * 0.5;
line.appendChild(dot);
// Remove the dot after animation completes
setTimeout(() => {
dot.remove();
}, (duration + delay) * 1000);
}
});
</script>
</body>
</html>