Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9543bcbc8a | |||
| 575562cf10 | |||
| d8c62513d4 | |||
| bbfa40194e |
@@ -14,7 +14,365 @@ export default function RootLayout({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body className={inter.className}>{children}
|
<head>
|
||||||
|
<script
|
||||||
|
id="webgl-fluid-simulation"
|
||||||
|
type="module"
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `
|
||||||
|
(function() {
|
||||||
|
const isMobile = () => window.innerWidth < 768;
|
||||||
|
|
||||||
|
if (isMobile()) return;
|
||||||
|
|
||||||
|
const canvas = document.getElementById('fluid-canvas');
|
||||||
|
if (!canvas) return;
|
||||||
|
|
||||||
|
const gl = canvas.getContext('webgl2', { antialias: true, alpha: true });
|
||||||
|
if (!gl) return;
|
||||||
|
|
||||||
|
let width = canvas.clientWidth;
|
||||||
|
let height = canvas.clientHeight;
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
|
||||||
|
const pixelRatio = window.devicePixelRatio || 1;
|
||||||
|
canvas.width *= pixelRatio;
|
||||||
|
canvas.height *= pixelRatio;
|
||||||
|
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
const medicalBlue = [0.086, 0.282, 0.612];
|
||||||
|
const medicalTeal = [0.2, 0.6, 0.8];
|
||||||
|
const lightBlue = [0.3, 0.7, 0.9];
|
||||||
|
|
||||||
|
const vertexShader = \`#version 300 es
|
||||||
|
precision highp float;
|
||||||
|
in vec2 position;
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
const advectionShader = \`#version 300 es
|
||||||
|
precision highp float;
|
||||||
|
uniform sampler2D velocityTexture;
|
||||||
|
uniform sampler2D fieldTexture;
|
||||||
|
uniform vec2 texelSize;
|
||||||
|
uniform float dt;
|
||||||
|
in vec2 uv;
|
||||||
|
out vec4 outColor;
|
||||||
|
void main() {
|
||||||
|
vec2 coord = uv - dt * texture(velocityTexture, uv).xy * texelSize;
|
||||||
|
coord = clamp(coord, texelSize, 1.0 - texelSize);
|
||||||
|
outColor = texture(fieldTexture, coord);
|
||||||
|
}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
const diffusionShader = \`#version 300 es
|
||||||
|
precision highp float;
|
||||||
|
uniform sampler2D velocityTexture;
|
||||||
|
uniform float diffusion;
|
||||||
|
uniform float dt;
|
||||||
|
uniform vec2 texelSize;
|
||||||
|
in vec2 uv;
|
||||||
|
out vec4 outColor;
|
||||||
|
void main() {
|
||||||
|
vec4 center = texture(velocityTexture, uv);
|
||||||
|
vec4 north = texture(velocityTexture, uv + vec2(0.0, texelSize.y));
|
||||||
|
vec4 south = texture(velocityTexture, uv - vec2(0.0, texelSize.y));
|
||||||
|
vec4 east = texture(velocityTexture, uv + vec2(texelSize.x, 0.0));
|
||||||
|
vec4 west = texture(velocityTexture, uv - vec2(texelSize.x, 0.0));
|
||||||
|
vec4 avg = (north + south + east + west) * 0.25;
|
||||||
|
outColor = mix(center, avg, diffusion);
|
||||||
|
}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
const divergenceShader = \`#version 300 es
|
||||||
|
precision highp float;
|
||||||
|
uniform sampler2D velocityTexture;
|
||||||
|
uniform vec2 texelSize;
|
||||||
|
in vec2 uv;
|
||||||
|
out vec4 outColor;
|
||||||
|
void main() {
|
||||||
|
vec2 vE = texture(velocityTexture, uv + vec2(texelSize.x, 0.0)).xy;
|
||||||
|
vec2 vW = texture(velocityTexture, uv - vec2(texelSize.x, 0.0)).xy;
|
||||||
|
vec2 vN = texture(velocityTexture, uv + vec2(0.0, texelSize.y)).xy;
|
||||||
|
vec2 vS = texture(velocityTexture, uv - vec2(0.0, texelSize.y)).xy;
|
||||||
|
float div = 0.5 * ((vE.x - vW.x) / texelSize.x + (vN.y - vS.y) / texelSize.y);
|
||||||
|
outColor = vec4(div);
|
||||||
|
}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
const pressureShader = \`#version 300 es
|
||||||
|
precision highp float;
|
||||||
|
uniform sampler2D pressureTexture;
|
||||||
|
uniform sampler2D divergenceTexture;
|
||||||
|
uniform vec2 texelSize;
|
||||||
|
in vec2 uv;
|
||||||
|
out vec4 outColor;
|
||||||
|
void main() {
|
||||||
|
float pN = texture(pressureTexture, uv + vec2(0.0, texelSize.y)).x;
|
||||||
|
float pS = texture(pressureTexture, uv - vec2(0.0, texelSize.y)).x;
|
||||||
|
float pE = texture(pressureTexture, uv + vec2(texelSize.x, 0.0)).x;
|
||||||
|
float pW = texture(pressureTexture, uv - vec2(texelSize.x, 0.0)).x;
|
||||||
|
float div = texture(divergenceTexture, uv).x;
|
||||||
|
float pressure = (pN + pS + pE + pW - div) * 0.25;
|
||||||
|
outColor = vec4(pressure);
|
||||||
|
}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
const projectionShader = \`#version 300 es
|
||||||
|
precision highp float;
|
||||||
|
uniform sampler2D velocityTexture;
|
||||||
|
uniform sampler2D pressureTexture;
|
||||||
|
uniform vec2 texelSize;
|
||||||
|
in vec2 uv;
|
||||||
|
out vec4 outColor;
|
||||||
|
void main() {
|
||||||
|
float pN = texture(pressureTexture, uv + vec2(0.0, texelSize.y)).x;
|
||||||
|
float pS = texture(pressureTexture, uv - vec2(0.0, texelSize.y)).x;
|
||||||
|
float pE = texture(pressureTexture, uv + vec2(texelSize.x, 0.0)).x;
|
||||||
|
float pW = texture(pressureTexture, uv - vec2(texelSize.x, 0.0)).x;
|
||||||
|
vec2 velocity = texture(velocityTexture, uv).xy;
|
||||||
|
velocity -= 0.5 * vec2(pE - pW, pN - pS) / texelSize;
|
||||||
|
outColor = vec4(velocity, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
const renderShader = \`#version 300 es
|
||||||
|
precision highp float;
|
||||||
|
uniform sampler2D densityTexture;
|
||||||
|
in vec2 uv;
|
||||||
|
out vec4 outColor;
|
||||||
|
void main() {
|
||||||
|
float density = texture(densityTexture, uv).x;
|
||||||
|
vec3 color = mix(vec3(0.086, 0.282, 0.612), vec3(0.2, 0.6, 0.8), density);
|
||||||
|
outColor = vec4(color, 0.3 * density);
|
||||||
|
}
|
||||||
|
\`;
|
||||||
|
|
||||||
|
function compileShader(source, type) {
|
||||||
|
const shader = gl.createShader(type);
|
||||||
|
gl.shaderSource(shader, source);
|
||||||
|
gl.compileShader(shader);
|
||||||
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
|
console.error(gl.getShaderInfoLog(shader));
|
||||||
|
gl.deleteShader(shader);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createProgram(vertexSource, fragmentSource) {
|
||||||
|
const vertShader = compileShader(vertexSource, gl.VERTEX_SHADER);
|
||||||
|
const fragShader = compileShader(fragmentSource, gl.FRAGMENT_SHADER);
|
||||||
|
if (!vertShader || !fragShader) return null;
|
||||||
|
|
||||||
|
const program = gl.createProgram();
|
||||||
|
gl.attachShader(program, vertShader);
|
||||||
|
gl.attachShader(program, fragShader);
|
||||||
|
gl.linkProgram(program);
|
||||||
|
|
||||||
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||||
|
console.error(gl.getProgramInfoLog(program));
|
||||||
|
gl.deleteProgram(program);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.deleteShader(vertShader);
|
||||||
|
gl.deleteShader(fragShader);
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFramebuffer(texture) {
|
||||||
|
const fb = gl.createFramebuffer();
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||||
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
||||||
|
return fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTexture(width, height, internalFormat, format, type) {
|
||||||
|
const texture = gl.createTexture();
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, null);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
const velocityTexture = createTexture(width, height, gl.RG16F, gl.RG, gl.FLOAT);
|
||||||
|
const velocityTexture2 = createTexture(width, height, gl.RG16F, gl.RG, gl.FLOAT);
|
||||||
|
const densityTexture = createTexture(width, height, gl.R16F, gl.RED, gl.FLOAT);
|
||||||
|
const densityTexture2 = createTexture(width, height, gl.R16F, gl.RED, gl.FLOAT);
|
||||||
|
const divergenceTexture = createTexture(width, height, gl.R16F, gl.RED, gl.FLOAT);
|
||||||
|
const pressureTexture = createTexture(width, height, gl.R16F, gl.RED, gl.FLOAT);
|
||||||
|
const pressureTexture2 = createTexture(width, height, gl.R16F, gl.RED, gl.FLOAT);
|
||||||
|
|
||||||
|
const velocityFb = createFramebuffer(velocityTexture);
|
||||||
|
const velocityFb2 = createFramebuffer(velocityTexture2);
|
||||||
|
const densityFb = createFramebuffer(densityTexture);
|
||||||
|
const densityFb2 = createFramebuffer(densityTexture2);
|
||||||
|
const divergenceFb = createFramebuffer(divergenceTexture);
|
||||||
|
const pressureFb = createFramebuffer(pressureTexture);
|
||||||
|
const pressureFb2 = createFramebuffer(pressureTexture2);
|
||||||
|
|
||||||
|
const programs = {
|
||||||
|
advection: createProgram(vertexShader, advectionShader),
|
||||||
|
diffusion: createProgram(vertexShader, diffusionShader),
|
||||||
|
divergence: createProgram(vertexShader, divergenceShader),
|
||||||
|
pressure: createProgram(vertexShader, pressureShader),
|
||||||
|
projection: createProgram(vertexShader, projectionShader),
|
||||||
|
render: createProgram(vertexShader, renderShader),
|
||||||
|
};
|
||||||
|
|
||||||
|
const vao = gl.createVertexArray();
|
||||||
|
gl.bindVertexArray(vao);
|
||||||
|
|
||||||
|
const positionBuffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
||||||
|
|
||||||
|
for (const program of Object.values(programs)) {
|
||||||
|
const positionLoc = gl.getAttribLocation(program, 'position');
|
||||||
|
gl.enableVertexAttribArray(positionLoc);
|
||||||
|
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 8, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mouseX = width / 2;
|
||||||
|
let mouseY = height / 2;
|
||||||
|
let mouseVelX = 0;
|
||||||
|
let mouseVelY = 0;
|
||||||
|
let prevMouseX = mouseX;
|
||||||
|
let prevMouseY = mouseY;
|
||||||
|
|
||||||
|
canvas.addEventListener('mousemove', (e) => {
|
||||||
|
prevMouseX = mouseX;
|
||||||
|
prevMouseY = mouseY;
|
||||||
|
mouseX = e.clientX * pixelRatio;
|
||||||
|
mouseY = (window.innerHeight - e.clientY) * pixelRatio;
|
||||||
|
mouseVelX = mouseX - prevMouseX;
|
||||||
|
mouseVelY = mouseY - prevMouseY;
|
||||||
|
});
|
||||||
|
|
||||||
|
function bindTexture(program, uniformName, texture, unit) {
|
||||||
|
const loc = gl.getUniformLocation(program, uniformName);
|
||||||
|
gl.uniform1i(loc, unit);
|
||||||
|
gl.activeTexture(gl.TEXTURE0 + unit);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderFullscreen(program, fb) {
|
||||||
|
gl.useProgram(program);
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||||
|
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
let time = 0;
|
||||||
|
let lastFrameTime = performance.now();
|
||||||
|
let frameCount = 0;
|
||||||
|
|
||||||
|
function frame(currentTime) {
|
||||||
|
const deltaTime = Math.min((currentTime - lastFrameTime) / 1000, 0.016);
|
||||||
|
lastFrameTime = currentTime;
|
||||||
|
frameCount++;
|
||||||
|
time += deltaTime;
|
||||||
|
|
||||||
|
const texelSize = [1 / width, 1 / height];
|
||||||
|
const dt = 0.016;
|
||||||
|
|
||||||
|
gl.bindVertexArray(vao);
|
||||||
|
|
||||||
|
// Add density at mouse
|
||||||
|
gl.useProgram(programs.render);
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, densityFb);
|
||||||
|
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||||
|
bindTexture(programs.render, 'densityTexture', densityTexture, 0);
|
||||||
|
|
||||||
|
// Add velocity at mouse
|
||||||
|
gl.useProgram(programs.advection);
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, velocityFb2);
|
||||||
|
bindTexture(programs.advection, 'velocityTexture', velocityTexture, 0);
|
||||||
|
bindTexture(programs.advection, 'fieldTexture', velocityTexture, 1);
|
||||||
|
gl.uniform2f(gl.getUniformLocation(programs.advection, 'texelSize'), texelSize[0], texelSize[1]);
|
||||||
|
gl.uniform1f(gl.getUniformLocation(programs.advection, 'dt'), dt * 0.1);
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
[velocityTexture, velocityTexture2] = [velocityTexture2, velocityTexture];
|
||||||
|
|
||||||
|
// Advect density
|
||||||
|
gl.useProgram(programs.advection);
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, densityFb2);
|
||||||
|
bindTexture(programs.advection, 'velocityTexture', velocityTexture, 0);
|
||||||
|
bindTexture(programs.advection, 'fieldTexture', densityTexture, 1);
|
||||||
|
gl.uniform2f(gl.getUniformLocation(programs.advection, 'texelSize'), texelSize[0], texelSize[1]);
|
||||||
|
gl.uniform1f(gl.getUniformLocation(programs.advection, 'dt'), dt);
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
[densityTexture, densityTexture2] = [densityTexture2, densityTexture];
|
||||||
|
|
||||||
|
// Diffuse velocity
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
gl.useProgram(programs.diffusion);
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, velocityFb2);
|
||||||
|
bindTexture(programs.diffusion, 'velocityTexture', velocityTexture, 0);
|
||||||
|
gl.uniform1f(gl.getUniformLocation(programs.diffusion, 'diffusion'), 0.0001);
|
||||||
|
gl.uniform1f(gl.getUniformLocation(programs.diffusion, 'dt'), dt);
|
||||||
|
gl.uniform2f(gl.getUniformLocation(programs.diffusion, 'texelSize'), texelSize[0], texelSize[1]);
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||||
|
[velocityTexture, velocityTexture2] = [velocityTexture2, velocityTexture];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Project velocity
|
||||||
|
gl.useProgram(programs.divergence);
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, divergenceFb);
|
||||||
|
bindTexture(programs.divergence, 'velocityTexture', velocityTexture, 0);
|
||||||
|
gl.uniform2f(gl.getUniformLocation(programs.divergence, 'texelSize'), texelSize[0], texelSize[1]);
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
gl.useProgram(programs.pressure);
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, pressureFb2);
|
||||||
|
bindTexture(programs.pressure, 'pressureTexture', pressureTexture, 0);
|
||||||
|
bindTexture(programs.pressure, 'divergenceTexture', divergenceTexture, 1);
|
||||||
|
gl.uniform2f(gl.getUniformLocation(programs.pressure, 'texelSize'), texelSize[0], texelSize[1]);
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||||
|
[pressureTexture, pressureTexture2] = [pressureTexture2, pressureTexture];
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.useProgram(programs.projection);
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, velocityFb2);
|
||||||
|
bindTexture(programs.projection, 'velocityTexture', velocityTexture, 0);
|
||||||
|
bindTexture(programs.projection, 'pressureTexture', pressureTexture, 1);
|
||||||
|
gl.uniform2f(gl.getUniformLocation(programs.projection, 'texelSize'), texelSize[0], texelSize[1]);
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||||
|
[velocityTexture, velocityTexture2] = [velocityTexture2, velocityTexture];
|
||||||
|
|
||||||
|
// Render to screen
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||||
|
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||||
|
gl.useProgram(programs.render);
|
||||||
|
bindTexture(programs.render, 'densityTexture', densityTexture, 0);
|
||||||
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
if (frameCount < 300) {
|
||||||
|
requestAnimationFrame(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.clearColor(0, 0, 0, 0);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
requestAnimationFrame(frame);
|
||||||
|
})();
|
||||||
|
`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
|
<body className={inter.className}>
|
||||||
|
{children}
|
||||||
|
|
||||||
<script
|
<script
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: `
|
__html: `
|
||||||
|
|||||||
497
src/app/page.tsx
497
src/app/page.tsx
@@ -10,9 +10,56 @@ import TestimonialCardOne from "@/components/sections/testimonial/TestimonialCar
|
|||||||
import SocialProofOne from "@/components/sections/socialProof/SocialProofOne";
|
import SocialProofOne from "@/components/sections/socialProof/SocialProofOne";
|
||||||
import ContactText from "@/components/sections/contact/ContactText";
|
import ContactText from "@/components/sections/contact/ContactText";
|
||||||
import FooterBaseCard from "@/components/sections/footer/FooterBaseCard";
|
import FooterBaseCard from "@/components/sections/footer/FooterBaseCard";
|
||||||
import { Award, Eye, Hand, Scissors, Shield, Sparkles, Zap } from "lucide-react";
|
import { Award, Eye, Hand, Scissors, Shield, Sparkles, Zap, Check } from "lucide-react";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
export default function LandingPage() {
|
export default function LandingPage() {
|
||||||
|
useEffect(() => {
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.id = 'fluid-canvas';
|
||||||
|
canvas.style.position = 'fixed';
|
||||||
|
canvas.style.top = '0';
|
||||||
|
canvas.style.left = '0';
|
||||||
|
canvas.style.width = '100%';
|
||||||
|
canvas.style.height = '100%';
|
||||||
|
canvas.style.pointerEvents = 'none';
|
||||||
|
canvas.style.zIndex = '1';
|
||||||
|
canvas.style.display = window.innerWidth < 768 ? 'none' : 'block';
|
||||||
|
|
||||||
|
// Create static gradient fallback for mobile
|
||||||
|
const gradient = document.createElement('div');
|
||||||
|
gradient.style.position = 'fixed';
|
||||||
|
gradient.style.top = '0';
|
||||||
|
gradient.style.left = '0';
|
||||||
|
gradient.style.width = '100%';
|
||||||
|
gradient.style.height = '100%';
|
||||||
|
gradient.style.background = 'linear-gradient(135deg, #0f3d73 0%, #1e7a8f 50%, #2b9fb5 100%)';
|
||||||
|
gradient.style.pointerEvents = 'none';
|
||||||
|
gradient.style.zIndex = '0';
|
||||||
|
gradient.style.display = window.innerWidth < 768 ? 'block' : 'none';
|
||||||
|
|
||||||
|
document.body.appendChild(canvas);
|
||||||
|
document.body.appendChild(gradient);
|
||||||
|
|
||||||
|
const handleResize = () => {
|
||||||
|
const isMobile = window.innerWidth < 768;
|
||||||
|
canvas.style.display = isMobile ? 'none' : 'block';
|
||||||
|
gradient.style.display = isMobile ? 'block' : 'none';
|
||||||
|
if (!isMobile && canvas.width === 0) {
|
||||||
|
canvas.width = canvas.clientWidth;
|
||||||
|
canvas.height = canvas.clientHeight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('resize', handleResize);
|
||||||
|
canvas.remove();
|
||||||
|
gradient.remove();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
defaultButtonVariant="hover-magnetic"
|
defaultButtonVariant="hover-magnetic"
|
||||||
@@ -26,237 +73,239 @@ export default function LandingPage() {
|
|||||||
secondaryButtonStyle="radial-glow"
|
secondaryButtonStyle="radial-glow"
|
||||||
headingFontWeight="normal"
|
headingFontWeight="normal"
|
||||||
>
|
>
|
||||||
<div id="nav" data-section="nav">
|
<div style={{ position: 'relative', zIndex: 2 }}>
|
||||||
<NavbarLayoutFloatingOverlay
|
<div id="nav" data-section="nav">
|
||||||
brandName="Advanced Hand Surgery"
|
<NavbarLayoutFloatingOverlay
|
||||||
navItems={[
|
brandName="Advanced Hand Surgery"
|
||||||
{ name: "Services", id: "services" },
|
navItems={[
|
||||||
{ name: "Expertise", id: "surgeon-expertise" },
|
{ name: "Services", id: "services" },
|
||||||
{ name: "Conditions", id: "conditions" },
|
{ name: "Expertise", id: "surgeon-expertise" },
|
||||||
{ name: "Testimonials", id: "testimonials" },
|
{ name: "Conditions", id: "conditions" },
|
||||||
{ name: "Contact", id: "contact" },
|
{ name: "Testimonials", id: "testimonials" },
|
||||||
]}
|
{ name: "Contact", id: "contact" },
|
||||||
button={{
|
]}
|
||||||
text: "Request Consultation", href: "#contact"
|
button={{
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="hero" data-section="hero">
|
|
||||||
<HeroBillboardRotatedCarousel
|
|
||||||
title="Advanced Hand & Wrist Surgery"
|
|
||||||
description="Board-Certified Hand Surgeons Providing Precision Treatment for Hand, Wrist, and Nerve Conditions"
|
|
||||||
tag="Board Certified"
|
|
||||||
tagIcon={Shield}
|
|
||||||
tagAnimation="slide-up"
|
|
||||||
background={{ variant: "plain" }}
|
|
||||||
buttons={[
|
|
||||||
{
|
|
||||||
text: "Request Consultation", href: "#contact"
|
text: "Request Consultation", href: "#contact"
|
||||||
},
|
}}
|
||||||
]}
|
/>
|
||||||
carouselItems={[
|
</div>
|
||||||
{
|
|
||||||
id: "carousel-1", imageSrc: "http://img.b2bpic.net/free-photo/close-up-doctor-checking-joints_23-2148504551.jpg?_wi=1", imageAlt: "hand surgeon medical professional orthopedic clinical"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "carousel-2", imageSrc: "http://img.b2bpic.net/free-photo/young-hispanic-woman-business-worker-suffering-wrist-pain-office_839833-33397.jpg", imageAlt: "carpal tunnel hand therapy wrist pain medical"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "carousel-3", imageSrc: "http://img.b2bpic.net/free-photo/closeup-x-ray-film-fractured-finger_53876-32061.jpg", imageAlt: "hand fracture bone healing medical treatment x-ray"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "carousel-4", imageSrc: "http://img.b2bpic.net/free-photo/close-up-doctor-checking-joints_23-2148504551.jpg?_wi=2", imageAlt: "arthroscopy wrist surgery surgical procedure medical"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "carousel-5", imageSrc: "http://img.b2bpic.net/free-photo/male-student-practicing-medicine_23-2149040276.jpg?_wi=1", imageAlt: "male surgeon medical professional doctor portrait clinical"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "carousel-6", imageSrc: "http://img.b2bpic.net/free-photo/senior-medic-showing-diagnosis-laptop-sick-patient-explaining-disease-medicine-treatment-checkup-visit-appointment-waiting-room-doctor-woman-doing-medical-examination_482257-48869.jpg", imageAlt: "hospital medical facility healthcare clinical"
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
autoPlay={true}
|
|
||||||
autoPlayInterval={4000}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="services" data-section="services">
|
<div id="hero" data-section="hero">
|
||||||
<FeatureBento
|
<HeroBillboardRotatedCarousel
|
||||||
title="Our Services"
|
tag="Board Certified & Trusted"
|
||||||
description="Comprehensive hand and wrist surgical solutions utilizing advanced techniques and proven treatment protocols"
|
tagIcon={Check}
|
||||||
features={[
|
tagAnimation="slide-up"
|
||||||
{
|
title="Advanced Hand & Wrist Surgery"
|
||||||
title: "Carpal Tunnel Surgery", description: "Precision surgical decompression to relieve nerve pressure and restore hand function", bentoComponent: "reveal-icon", icon: Zap,
|
description="Board-Certified Hand Surgeons Providing Precision Treatment for Hand, Wrist, and Nerve Conditions"
|
||||||
},
|
background={{ variant: "plain" }}
|
||||||
{
|
buttons={[
|
||||||
title: "Hand Fracture Repair", description: "Expert surgical restoration of fractured bones ensuring optimal healing and mobility", bentoComponent: "reveal-icon", icon: Shield,
|
{
|
||||||
},
|
text: "Request Consultation", href: "#contact"
|
||||||
{
|
},
|
||||||
title: "Tendon & Ligament Injuries", description: "Advanced microsurgical techniques for complex soft tissue reconstruction", bentoComponent: "reveal-icon", icon: Sparkles,
|
]}
|
||||||
},
|
carouselItems={[
|
||||||
{
|
{
|
||||||
title: "Wrist Arthroscopy", description: "Minimally invasive diagnostic and therapeutic procedures for wrist conditions", bentoComponent: "reveal-icon", icon: Eye,
|
id: "carousel-1", imageSrc: "http://img.b2bpic.net/free-photo/close-up-doctor-checking-joints_23-2148504551.jpg?_wi=1", imageAlt: "hand surgeon medical professional orthopedic clinical"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Dupuytren's Contracture", description: "Surgical treatment of hand contracture with precision tissue release techniques", bentoComponent: "reveal-icon", icon: Scissors,
|
id: "carousel-2", imageSrc: "http://img.b2bpic.net/free-photo/young-hispanic-woman-business-worker-suffering-wrist-pain-office_839833-33397.jpg", imageAlt: "carpal tunnel hand therapy wrist pain medical"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Trigger Finger Treatment", description: "Effective surgical and non-surgical solutions for finger lock and pain relief", bentoComponent: "reveal-icon", icon: Hand,
|
id: "carousel-3", imageSrc: "http://img.b2bpic.net/free-photo/closeup-x-ray-film-fractured-finger_53876-32061.jpg", imageAlt: "hand fracture bone healing medical treatment x-ray"
|
||||||
},
|
},
|
||||||
]}
|
{
|
||||||
animationType="blur-reveal"
|
id: "carousel-4", imageSrc: "http://img.b2bpic.net/free-photo/close-up-doctor-checking-joints_23-2148504551.jpg?_wi=2", imageAlt: "arthroscopy wrist surgery surgical procedure medical"
|
||||||
textboxLayout="default"
|
},
|
||||||
useInvertedBackground={false}
|
{
|
||||||
/>
|
id: "carousel-5", imageSrc: "http://img.b2bpic.net/free-photo/male-student-practicing-medicine_23-2149040276.jpg?_wi=1", imageAlt: "male surgeon medical professional doctor portrait clinical"
|
||||||
</div>
|
},
|
||||||
|
{
|
||||||
|
id: "carousel-6", imageSrc: "http://img.b2bpic.net/free-photo/senior-medic-showing-diagnosis-laptop-sick-patient-explaining-disease-medicine-treatment-checkup-visit-appointment-waiting-room-doctor-woman-doing-medical-examination_482257-48869.jpg", imageAlt: "hospital medical facility healthcare clinical"
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
autoPlay={true}
|
||||||
|
autoPlayInterval={4000}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="surgeon-expertise" data-section="surgeon-expertise">
|
<div id="services" data-section="services">
|
||||||
<MetricSplitMediaAbout
|
<FeatureBento
|
||||||
tag="Surgical Excellence"
|
title="Our Services"
|
||||||
tagIcon={Award}
|
description="Comprehensive hand and wrist surgical solutions utilizing advanced techniques and proven treatment protocols"
|
||||||
title="Board-Certified Expertise in Hand Surgery"
|
features={[
|
||||||
description="With over 15 years of specialized surgical experience, our hand surgeon brings fellowship training in hand and microsurgery from leading institutions. We are committed to providing the highest standard of care utilizing cutting-edge surgical techniques and proven clinical protocols."
|
{
|
||||||
metrics={[
|
title: "Carpal Tunnel Surgery", description: "Precision surgical decompression to relieve nerve pressure and restore hand function", bentoComponent: "reveal-icon", icon: Zap,
|
||||||
{ value: "15+", title: "Years of Surgical Experience" },
|
},
|
||||||
{ value: "2000+", title: "Successful Procedures" },
|
{
|
||||||
]}
|
title: "Hand Fracture Repair", description: "Expert surgical restoration of fractured bones ensuring optimal healing and mobility", bentoComponent: "reveal-icon", icon: Shield,
|
||||||
imageSrc="http://img.b2bpic.net/free-photo/male-student-practicing-medicine_23-2149040276.jpg?_wi=2"
|
},
|
||||||
imageAlt="Board-Certified Hand Surgeon"
|
{
|
||||||
mediaAnimation="blur-reveal"
|
title: "Tendon & Ligament Injuries", description: "Advanced microsurgical techniques for complex soft tissue reconstruction", bentoComponent: "reveal-icon", icon: Sparkles,
|
||||||
metricsAnimation="blur-reveal"
|
},
|
||||||
useInvertedBackground={false}
|
{
|
||||||
/>
|
title: "Wrist Arthroscopy", description: "Minimally invasive diagnostic and therapeutic procedures for wrist conditions", bentoComponent: "reveal-icon", icon: Eye,
|
||||||
</div>
|
},
|
||||||
|
{
|
||||||
|
title: "Dupuytren's Contracture", description: "Surgical treatment of hand contracture with precision tissue release techniques", bentoComponent: "reveal-icon", icon: Scissors,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Trigger Finger Treatment", description: "Effective surgical and non-surgical solutions for finger lock and pain relief", bentoComponent: "reveal-icon", icon: Hand,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
animationType="blur-reveal"
|
||||||
|
textboxLayout="default"
|
||||||
|
useInvertedBackground={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="conditions" data-section="conditions">
|
<div id="surgeon-expertise" data-section="surgeon-expertise">
|
||||||
<MetricCardSeven
|
<MetricSplitMediaAbout
|
||||||
title="Conditions We Treat"
|
tag="Surgical Excellence"
|
||||||
description="Expert diagnosis and treatment for a comprehensive range of hand and wrist conditions"
|
tagIcon={Award}
|
||||||
metrics={[
|
title="Board-Certified Expertise in Hand Surgery"
|
||||||
{
|
description="With over 15 years of specialized surgical experience, our hand surgeon brings fellowship training in hand and microsurgery from leading institutions. We are committed to providing the highest standard of care utilizing cutting-edge surgical techniques and proven clinical protocols."
|
||||||
id: "condition-1", value: "CTS", title: "Carpal Tunnel Syndrome", items: [
|
metrics={[
|
||||||
"Nerve compression relief", "Minimally invasive approach", "Rapid recovery protocol"
|
{ value: "15+", title: "Years of Surgical Experience" },
|
||||||
],
|
{ value: "2000+", title: "Successful Procedures" },
|
||||||
},
|
]}
|
||||||
{
|
imageSrc="http://img.b2bpic.net/free-photo/male-student-practicing-medicine_23-2149040276.jpg?_wi=2"
|
||||||
id: "condition-2", value: "TF", title: "Trigger Finger", items: [
|
imageAlt="Board-Certified Hand Surgeon"
|
||||||
"Conservative treatment options", "Surgical correction available", "Full functional restoration"
|
mediaAnimation="blur-reveal"
|
||||||
],
|
metricsAnimation="blur-reveal"
|
||||||
},
|
useInvertedBackground={false}
|
||||||
{
|
/>
|
||||||
id: "condition-3", value: "OA", title: "Hand Arthritis", items: [
|
</div>
|
||||||
"Advanced imaging diagnostics", "Pain management strategies", "Joint preservation techniques"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "condition-4", value: "WP", title: "Wrist Pain", items: [
|
|
||||||
"Comprehensive evaluation", "Conservative interventions", "Surgical options when needed"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
animationType="blur-reveal"
|
|
||||||
textboxLayout="default"
|
|
||||||
useInvertedBackground={false}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="testimonials" data-section="testimonials">
|
<div id="conditions" data-section="conditions">
|
||||||
<TestimonialCardOne
|
<MetricCardSeven
|
||||||
title="Patient Success Stories"
|
title="Conditions We Treat"
|
||||||
description="Real testimonials from patients who have experienced our expert care and achieved optimal outcomes"
|
description="Expert diagnosis and treatment for a comprehensive range of hand and wrist conditions"
|
||||||
testimonials={[
|
metrics={[
|
||||||
{
|
{
|
||||||
id: "testimonial-1", name: "Margaret Johnson", role: "Patient", company: "Carpal Tunnel Surgery", rating: 5,
|
id: "condition-1", value: "CTS", title: "Carpal Tunnel Syndrome", items: [
|
||||||
imageSrc: "http://img.b2bpic.net/free-photo/smiling-middle-aged-attractive-woman-showing-thumb-up-outdoors_1262-12526.jpg", imageAlt: "Margaret Johnson"
|
"Nerve compression relief", "Minimally invasive approach", "Rapid recovery protocol"
|
||||||
},
|
],
|
||||||
{
|
},
|
||||||
id: "testimonial-2", name: "David Chen", role: "Patient", company: "Hand Fracture Repair", rating: 5,
|
{
|
||||||
imageSrc: "http://img.b2bpic.net/free-photo/couple-suffering-from-infertility_23-2149430773.jpg?_wi=1", imageAlt: "David Chen"
|
id: "condition-2", value: "TF", title: "Trigger Finger", items: [
|
||||||
},
|
"Conservative treatment options", "Surgical correction available", "Full functional restoration"
|
||||||
{
|
],
|
||||||
id: "testimonial-3", name: "Patricia Rodriguez", role: "Patient", company: "Trigger Finger Treatment", rating: 5,
|
},
|
||||||
imageSrc: "http://img.b2bpic.net/free-photo/happy-mature-woman-wheelchair-holding-hands-with-her-doctor-hospital-hallway_637285-705.jpg", imageAlt: "Patricia Rodriguez"
|
{
|
||||||
},
|
id: "condition-3", value: "OA", title: "Hand Arthritis", items: [
|
||||||
{
|
"Advanced imaging diagnostics", "Pain management strategies", "Joint preservation techniques"
|
||||||
id: "testimonial-4", name: "James Wilson", role: "Patient", company: "Wrist Arthroscopy", rating: 5,
|
],
|
||||||
imageSrc: "http://img.b2bpic.net/free-photo/couple-suffering-from-infertility_23-2149430773.jpg?_wi=2", imageAlt: "James Wilson"
|
},
|
||||||
},
|
{
|
||||||
]}
|
id: "condition-4", value: "WP", title: "Wrist Pain", items: [
|
||||||
gridVariant="uniform-all-items-equal"
|
"Comprehensive evaluation", "Conservative interventions", "Surgical options when needed"
|
||||||
animationType="blur-reveal"
|
],
|
||||||
textboxLayout="default"
|
},
|
||||||
useInvertedBackground={false}
|
]}
|
||||||
/>
|
animationType="blur-reveal"
|
||||||
</div>
|
textboxLayout="default"
|
||||||
|
useInvertedBackground={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="credentials" data-section="credentials">
|
<div id="testimonials" data-section="testimonials">
|
||||||
<SocialProofOne
|
<TestimonialCardOne
|
||||||
title="Insurance & Board Certifications"
|
title="Patient Success Stories"
|
||||||
description="We accept major insurance plans and maintain board certifications from leading medical organizations"
|
description="Real testimonials from patients who have experienced our expert care and achieved optimal outcomes"
|
||||||
names={[
|
testimonials={[
|
||||||
"Blue Cross", "Aetna", "Cigna", "United Healthcare", "Humana", "Medicare", "AAOS", "ABOS"
|
{
|
||||||
]}
|
id: "testimonial-1", name: "Margaret Johnson", role: "Patient", company: "Carpal Tunnel Surgery", rating: 5,
|
||||||
textboxLayout="default"
|
imageSrc: "http://img.b2bpic.net/free-photo/smiling-middle-aged-attractive-woman-showing-thumb-up-outdoors_1262-12526.jpg", imageAlt: "Margaret Johnson"
|
||||||
useInvertedBackground={false}
|
},
|
||||||
speed={40}
|
{
|
||||||
showCard={true}
|
id: "testimonial-2", name: "David Chen", role: "Patient", company: "Hand Fracture Repair", rating: 5,
|
||||||
/>
|
imageSrc: "http://img.b2bpic.net/free-photo/couple-suffering-from-infertility_23-2149430773.jpg?_wi=1", imageAlt: "David Chen"
|
||||||
</div>
|
},
|
||||||
|
{
|
||||||
|
id: "testimonial-3", name: "Patricia Rodriguez", role: "Patient", company: "Trigger Finger Treatment", rating: 5,
|
||||||
|
imageSrc: "http://img.b2bpic.net/free-photo/happy-mature-woman-wheelchair-holding-hands-with-her-doctor-hospital-hallway_637285-705.jpg", imageAlt: "Patricia Rodriguez"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "testimonial-4", name: "James Wilson", role: "Patient", company: "Wrist Arthroscopy", rating: 5,
|
||||||
|
imageSrc: "http://img.b2bpic.net/free-photo/couple-suffering-from-infertility_23-2149430773.jpg?_wi=2", imageAlt: "James Wilson"
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
gridVariant="uniform-all-items-equal"
|
||||||
|
animationType="blur-reveal"
|
||||||
|
textboxLayout="default"
|
||||||
|
useInvertedBackground={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="contact" data-section="contact">
|
<div id="credentials" data-section="credentials">
|
||||||
<ContactText
|
<SocialProofOne
|
||||||
text="Ready to schedule your consultation? Contact our clinic today to discuss your hand and wrist health with our expert surgical team."
|
title="Insurance & Board Certifications"
|
||||||
animationType="reveal-blur"
|
description="We accept major insurance plans and maintain board certifications from leading medical organizations"
|
||||||
buttons={[
|
names={[
|
||||||
{
|
"Blue Cross", "Aetna", "Cigna", "United Healthcare", "Humana", "Medicare", "AAOS", "ABOS"
|
||||||
text: "Request Consultation", href: "#"
|
]}
|
||||||
},
|
textboxLayout="default"
|
||||||
{
|
useInvertedBackground={false}
|
||||||
text: "Call (555) 123-4567", href: "tel:+15551234567"
|
speed={40}
|
||||||
},
|
showCard={true}
|
||||||
]}
|
/>
|
||||||
background={{ variant: "plain" }}
|
</div>
|
||||||
useInvertedBackground={false}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="footer" data-section="footer">
|
<div id="contact" data-section="contact">
|
||||||
<FooterBaseCard
|
<ContactText
|
||||||
logoText="Advanced Hand Surgery"
|
text="Ready to schedule your consultation? Contact our clinic today to discuss your hand and wrist health with our expert surgical team."
|
||||||
columns={[
|
animationType="reveal-blur"
|
||||||
{
|
buttons={[
|
||||||
title: "Clinic", items: [
|
{
|
||||||
{ label: "About Us", href: "#surgeon-expertise" },
|
text: "Request Consultation", href: "#"
|
||||||
{ label: "Services", href: "#services" },
|
},
|
||||||
{ label: "Conditions", href: "#conditions" },
|
{
|
||||||
],
|
text: "Call (555) 123-4567", href: "tel:+15551234567"
|
||||||
},
|
},
|
||||||
{
|
]}
|
||||||
title: "Contact", items: [
|
background={{ variant: "plain" }}
|
||||||
{ label: "Phone: (555) 123-4567", href: "tel:+15551234567" },
|
useInvertedBackground={false}
|
||||||
{
|
/>
|
||||||
label: "Email: info@handsurgery.com", href: "mailto:info@handsurgery.com"
|
</div>
|
||||||
},
|
|
||||||
{ label: "Request Consultation", href: "#contact" },
|
<div id="footer" data-section="footer">
|
||||||
],
|
<FooterBaseCard
|
||||||
},
|
logoText="Advanced Hand Surgery"
|
||||||
{
|
columns={[
|
||||||
title: "Hours", items: [
|
{
|
||||||
{ label: "Monday - Friday: 8am - 5pm", href: "#" },
|
title: "Clinic", items: [
|
||||||
{ label: "Saturday: 9am - 1pm", href: "#" },
|
{ label: "About Us", href: "#surgeon-expertise" },
|
||||||
{ label: "Sunday: Closed", href: "#" },
|
{ label: "Services", href: "#services" },
|
||||||
],
|
{ label: "Conditions", href: "#conditions" },
|
||||||
},
|
],
|
||||||
{
|
},
|
||||||
title: "Legal", items: [
|
{
|
||||||
{ label: "Privacy Policy", href: "#" },
|
title: "Contact", items: [
|
||||||
{ label: "Terms of Service", href: "#" },
|
{ label: "Phone: (555) 123-4567", href: "tel:+15551234567" },
|
||||||
{ label: "Accessibility", href: "#" },
|
{
|
||||||
],
|
label: "Email: info@handsurgery.com", href: "mailto:info@handsurgery.com"
|
||||||
},
|
},
|
||||||
]}
|
{ label: "Request Consultation", href: "#contact" },
|
||||||
copyrightText="© 2025 Advanced Hand Surgery Clinic. All rights reserved."
|
],
|
||||||
/>
|
},
|
||||||
|
{
|
||||||
|
title: "Hours", items: [
|
||||||
|
{ label: "Monday - Friday: 8am - 5pm", href: "#" },
|
||||||
|
{ label: "Saturday: 9am - 1pm", href: "#" },
|
||||||
|
{ label: "Sunday: Closed", href: "#" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Legal", items: [
|
||||||
|
{ label: "Privacy Policy", href: "#" },
|
||||||
|
{ label: "Terms of Service", href: "#" },
|
||||||
|
{ label: "Accessibility", href: "#" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
copyrightText="© 2025 Advanced Hand Surgery Clinic. All rights reserved."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user