From ede4237281d79543b2daed110398f6b007f8a87d Mon Sep 17 00:00:00 2001 From: hardik Date: Fri, 29 May 2026 06:54:18 +0000 Subject: [PATCH] fix drone --- .dockerignore | 16 +- .drone.yml | 81 +- .vscode/extensions.json | 10 +- .vscode/settings.json | 12 +- .yarn/sdks/integrations.yml | 10 +- Dockerfile | 36 +- src/App.tsx | 64 +- src/components/Layout.css | 732 ++--- src/components/Layout.tsx | 620 ++-- src/components/ScrollCandle.css | 580 ++-- src/components/ScrollCandle.tsx | 198 +- src/index.css | 170 +- src/main.tsx | 26 +- src/pages/AboutPage.tsx | 260 +- src/pages/ContactPage.tsx | 264 +- src/pages/ProductsPage.tsx | 200 +- src/pages/about.css | 458 +-- src/pages/contact.css | 632 ++-- src/pages/home.css | 772 ++--- src/pages/home.tsx | 294 +- src/pages/products.css | 346 +-- src/theme.ts | 126 +- vite.config.ts | 58 +- yarn.lock | 5144 +++++++++++++++---------------- 24 files changed, 5554 insertions(+), 5555 deletions(-) diff --git a/.dockerignore b/.dockerignore index 01eaf7e..b93364c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,9 +1,9 @@ -node_modules -dist -build -.git -.gitignore -Dockerfile -.dockerignore -README.md +node_modules +dist +build +.git +.gitignore +Dockerfile +.dockerignore +README.md .env \ No newline at end of file diff --git a/.drone.yml b/.drone.yml index f32b897..ca674dd 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,41 +1,40 @@ -kind: pipeline -name: Build Image - -steps: - - name: Build Docker Image - image: plugins/docker - settings: - username: - from_secret: docker_username - password: - from_secret: docker_password - repo: git.midastix.com/ci-docker-repo-user/manicandles - registry: git.midastix.com - - when: - branch: - - main - event: - - push - - - name: Deploy Image - image: appleboy/drone-ssh - - settings: - host: server1.midastix.com - username: root - key: - from_secret: server_ssh_pkey - port: 22 - command_timeout: 5m - - script: - - echo "Deploying ManiCandles" - - sudo /opt/deployable/manicandles/docker/deploy.sh - - echo "Deployment Completed" - - when: - branch: - - main - event: - - push \ No newline at end of file +kind: pipeline +type: docker +name: Build Image + +steps: + - name: Build Docker Image + image: plugins/docker + settings: + username: + from_secret: docker_username + password: + from_secret: docker_password + repo: git.midastix.com/ci-docker-repo-user/manicandles + registry: git.midastix.com + + when: + branch: + - main + event: + - push + + - name: Deploy image + image: appleboy/drone-ssh + settings: + host: server1.midastix.com + username: root + key: + from_secret: server_ssh_pkey + port: 22 + command_timeout: 5m + script: + - echo "Deploying ManiCandles" + - sudo /opt/deployable/manicandles/docker/deploy.sh + - echo "Completed Deployment" + + when: + branch: + - main + event: + - push diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 06dd640..2f3d0aa 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,5 @@ -{ - "recommendations": [ - "arcanis.vscode-zipfs" - ] -} +{ + "recommendations": [ + "arcanis.vscode-zipfs" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index e068e48..5364a7f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ -{ - "search.exclude": { - "**/.yarn": true, - "**/.pnp.*": true - } -} +{ + "search.exclude": { + "**/.yarn": true, + "**/.pnp.*": true + } +} diff --git a/.yarn/sdks/integrations.yml b/.yarn/sdks/integrations.yml index aa9d0d0..4e3df39 100644 --- a/.yarn/sdks/integrations.yml +++ b/.yarn/sdks/integrations.yml @@ -1,5 +1,5 @@ -# This file is automatically generated by @yarnpkg/sdks. -# Manual changes might be lost! - -integrations: - - vscode +# This file is automatically generated by @yarnpkg/sdks. +# Manual changes might be lost! + +integrations: + - vscode diff --git a/Dockerfile b/Dockerfile index 7c660ab..4282524 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,19 @@ -FROM node:20-alpine AS build - -WORKDIR /app - -COPY package*.json ./ - -RUN npm install - -COPY . . - -RUN npm run build - -FROM nginx:alpine - -COPY --from=build /app/dist /usr/share/nginx/html - -EXPOSE 80 - +FROM node:20-alpine AS build + +WORKDIR /app + +COPY package*.json ./ + +RUN npm install + +COPY . . + +RUN npm run build + +FROM nginx:alpine + +COPY --from=build /app/dist /usr/share/nginx/html + +EXPOSE 80 + CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 92c3dcd..0c2c1e7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,32 +1,32 @@ -import { Switch, Route, Router as WouterRouter } from "wouter"; -import NotFound from "@/pages/not-found"; - -import { Layout } from "@/components/Layout"; -import Home from "@/pages/home"; -import ProductsPage from "@/pages/ProductsPage"; -import AboutPage from "@/pages/AboutPage"; -import ContactPage from "@/pages/ContactPage"; - -function Router() { - return ( - - - - - - - - ); -} - -function App() { - return ( - - - - - - ); -} - -export default App; +import { Switch, Route, Router as WouterRouter } from "wouter"; +import NotFound from "@/pages/not-found"; + +import { Layout } from "@/components/Layout"; +import Home from "@/pages/home"; +import ProductsPage from "@/pages/ProductsPage"; +import AboutPage from "@/pages/AboutPage"; +import ContactPage from "@/pages/ContactPage"; + +function Router() { + return ( + + + + + + + + ); +} + +function App() { + return ( + + + + + + ); +} + +export default App; diff --git a/src/components/Layout.css b/src/components/Layout.css index 1612ad1..151ee59 100644 --- a/src/components/Layout.css +++ b/src/components/Layout.css @@ -1,366 +1,366 @@ -/* ─── Layout.css — Header & Footer ──────────────────────── */ - -/* ══════════════════════════════════════════════════════════ - MARQUEE / TICKER BAR -══════════════════════════════════════════════════════════ */ -.ticker-bar { - background: var(--brand-purple-dark); - border-bottom: 1px solid rgba(212,162,76,0.25); - height: 36px; - overflow: hidden; - display: flex; - align-items: center; -} - -.ticker-track { - display: flex; - align-items: center; - gap: 0; - animation: ticker-scroll 28s linear infinite; - white-space: nowrap; - will-change: transform; -} - -.ticker-track:hover { - animation-play-state: paused; -} - -@keyframes ticker-scroll { - 0% { transform: translateX(0); } - 100% { transform: translateX(-50%); } -} - -.ticker-item { - display: inline-flex; - align-items: center; - gap: 0.6rem; - font-family: var(--font-display); - font-size: 0.62rem; - letter-spacing: 0.2em; - text-transform: uppercase; - color: rgba(255,255,255,0.85); - padding: 0 2.5rem; -} - -.ticker-dot { - width: 5px; - height: 5px; - border-radius: 50%; - background: var(--brand-gold); - flex-shrink: 0; - display: inline-block; -} - -/* ══════════════════════════════════════════════════════════ - LOGO -══════════════════════════════════════════════════════════ */ -.logo-text { - font-family: var(--font-script); - font-size: 2rem; - color: #ffffff; - transition: color 0.3s ease; - line-height: 1; -} -.logo-text:hover { color: var(--brand-gold-light); } - -.logo-img-wrap { - width: 44px; - height: 44px; - border-radius: 50%; - overflow: hidden; - border: 2px solid transparent; - transition: border-color 0.3s ease; -} -.logo-img-wrap:hover { border-color: var(--brand-gold); } - -/* ══════════════════════════════════════════════════════════ - NAV ITEM WITH DROPDOWN -══════════════════════════════════════════════════════════ */ -.nav-item { - position: relative; -} - -.nav-link { - font-family: var(--font-display); - font-size: 0.72rem; - letter-spacing: 0.2em; - text-transform: uppercase; - color: #ffffff; - text-decoration: none; - padding-bottom: 2px; - border-bottom: 2px solid transparent; - transition: border-color 0.3s ease, color 0.3s ease; - display: inline-flex; - align-items: center; - gap: 5px; - cursor: pointer; - background: none; - border-left: none; - border-right: none; - border-top: none; -} - -.nav-link:hover { - color: var(--brand-gold-light); - border-bottom-color: rgba(212,162,76,0.6); -} - -.nav-link.active { - color: var(--brand-gold-light); - border-bottom-color: var(--brand-gold); - border-bottom-width: 2.5px; - text-shadow: - 0 0 12px rgba(255,211,107,0.9), - 0 0 24px rgba(212,162,76,0.5); - font-weight: 600; - background: rgba(212,162,76,0.12); - border-radius: 4px; - padding: 3px 10px 5px; -} - -.nav-chevron { - transition: transform 0.25s ease; - opacity: 0.75; -} - -.nav-item:hover .nav-chevron { - transform: rotate(180deg); - opacity: 1; -} - -/* DROPDOWN PANEL */ -.nav-dropdown { - position: absolute; - top: calc(100% + 18px); - left: 50%; - transform: translateX(-50%) translateY(-8px); - min-width: 200px; - background: rgba(45, 13, 82, 0.96); - backdrop-filter: blur(16px); - -webkit-backdrop-filter: blur(16px); - border: 1px solid rgba(212,162,76,0.2); - border-radius: 8px; - padding: 0.6rem 0; - opacity: 0; - pointer-events: none; - transition: opacity 0.2s ease, transform 0.25s ease; - box-shadow: 0 16px 40px rgba(0,0,0,0.35); - z-index: 200; -} - -/* Arrow notch */ -.nav-dropdown::before { - content: ''; - position: absolute; - top: -7px; - left: 50%; - transform: translateX(-50%); - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-bottom: 7px solid rgba(212,162,76,0.25); -} - -.nav-dropdown::after { - content: ''; - position: absolute; - top: -6px; - left: 50%; - transform: translateX(-50%); - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-bottom: 7px solid rgba(45,13,82,0.96); -} - -.nav-item:hover .nav-dropdown { - opacity: 1; - pointer-events: auto; - transform: translateX(-50%) translateY(0); -} - -.dropdown-item { - display: flex; - align-items: center; - gap: 0.6rem; - padding: 0.65rem 1.25rem; - font-family: var(--font-sans); - font-size: 0.83rem; - color: rgba(255,255,255,0.78); - text-decoration: none; - transition: background 0.2s ease, color 0.2s ease, padding-left 0.2s ease; - white-space: nowrap; -} - -.dropdown-item:hover { - background: rgba(212,162,76,0.12); - color: var(--brand-gold-light); - padding-left: 1.6rem; -} - -.dropdown-divider { - height: 1px; - background: rgba(255,255,255,0.08); - margin: 0.4rem 0; -} - -/* ══════════════════════════════════════════════════════════ - MOBILE TOGGLE -══════════════════════════════════════════════════════════ */ -.mobile-toggle { - background: none; - border: none; - color: #ffffff; - cursor: pointer; - display: flex; - align-items: center; - padding: 4px; - transition: color 0.3s ease; -} -.mobile-toggle:hover { color: var(--brand-gold-light); } - -/* ══════════════════════════════════════════════════════════ - MOBILE DRAWER -══════════════════════════════════════════════════════════ */ -.mobile-menu { - background: rgba(45, 13, 82, 0.97); - backdrop-filter: blur(16px); - border-bottom: 1px solid rgba(212, 162, 76, 0.2); - padding: 1.5rem; - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -.mobile-nav-section { - display: flex; - flex-direction: column; -} - -.mobile-nav-link { - font-family: var(--font-display); - font-size: 0.85rem; - letter-spacing: 0.2em; - text-transform: uppercase; - color: #ffffff; - text-decoration: none; - padding: 0.8rem 0.5rem; - border-bottom: 1px solid rgba(255,255,255,0.07); - transition: color 0.3s ease, padding-left 0.2s ease; - display: block; -} - -.mobile-nav-link:hover { - color: var(--brand-gold-light); - padding-left: 0.75rem; -} - -.mobile-nav-link.active { - color: var(--brand-gold); - padding-left: 0.75rem; - text-shadow: 0 0 10px rgba(255,211,107,0.7); - font-weight: 600; -} - -.mobile-dropdown-items { - display: flex; - flex-direction: column; - padding: 0.25rem 0 0.5rem 1rem; - gap: 0.1rem; - border-bottom: 1px solid rgba(255,255,255,0.07); -} - -.mobile-dropdown-item { - font-family: var(--font-sans); - font-size: 0.82rem; - color: rgba(255,255,255,0.6); - text-decoration: none; - padding: 0.4rem 0.5rem; - transition: color 0.2s ease; -} - -.mobile-dropdown-item:hover { - color: var(--brand-gold-light); -} - -/* ══════════════════════════════════════════════════════════ - FOOTER -══════════════════════════════════════════════════════════ */ -.site-footer { - background: var(--brand-purple-dark); - color: #ffffff; - padding: 4rem 1.5rem; - margin-top: 5rem; -} - -.footer-inner { - max-width: 1280px; - margin: 0 auto; - display: grid; - grid-template-columns: 1fr; - gap: 3rem; - text-align: center; -} - -@media (min-width: 768px) { - .footer-inner { - grid-template-columns: 1fr 1fr 1fr; - text-align: left; - } -} - -.footer-col { - display: flex; - flex-direction: column; - align-items: center; - gap: 1rem; -} - -@media (min-width: 768px) { - .footer-col { align-items: flex-start; } -} - -.footer-tagline { - font-family: var(--font-serif); - font-style: italic; - font-size: 1.1rem; - color: rgba(255,255,255,0.7); -} - -.footer-heading { - font-family: var(--font-display); - font-size: 0.7rem; - letter-spacing: 0.25em; - text-transform: uppercase; - color: var(--brand-gold); - margin-bottom: 0.5rem; -} - -.footer-link { - color: rgba(255,255,255,0.75); - font-size: 0.9rem; - text-decoration: none; - transition: color 0.3s ease; -} -.footer-link:hover { color: var(--brand-gold-light); } - -.social-btn { - width: 40px; - height: 40px; - border-radius: 50%; - background: rgba(255,255,255,0.08); - display: flex; - align-items: center; - justify-content: center; - color: #ffffff; - text-decoration: none; - transition: background 0.3s ease, color 0.3s ease; -} -.social-btn:hover { - background: var(--brand-gold); - color: var(--brand-purple-dark); -} - -.footer-copy { - font-size: 0.78rem; - color: rgba(255,255,255,0.4); - margin-top: 1rem; -} +/* ─── Layout.css — Header & Footer ──────────────────────── */ + +/* ══════════════════════════════════════════════════════════ + MARQUEE / TICKER BAR +══════════════════════════════════════════════════════════ */ +.ticker-bar { + background: var(--brand-purple-dark); + border-bottom: 1px solid rgba(212,162,76,0.25); + height: 36px; + overflow: hidden; + display: flex; + align-items: center; +} + +.ticker-track { + display: flex; + align-items: center; + gap: 0; + animation: ticker-scroll 28s linear infinite; + white-space: nowrap; + will-change: transform; +} + +.ticker-track:hover { + animation-play-state: paused; +} + +@keyframes ticker-scroll { + 0% { transform: translateX(0); } + 100% { transform: translateX(-50%); } +} + +.ticker-item { + display: inline-flex; + align-items: center; + gap: 0.6rem; + font-family: var(--font-display); + font-size: 0.62rem; + letter-spacing: 0.2em; + text-transform: uppercase; + color: rgba(255,255,255,0.85); + padding: 0 2.5rem; +} + +.ticker-dot { + width: 5px; + height: 5px; + border-radius: 50%; + background: var(--brand-gold); + flex-shrink: 0; + display: inline-block; +} + +/* ══════════════════════════════════════════════════════════ + LOGO +══════════════════════════════════════════════════════════ */ +.logo-text { + font-family: var(--font-script); + font-size: 2rem; + color: #ffffff; + transition: color 0.3s ease; + line-height: 1; +} +.logo-text:hover { color: var(--brand-gold-light); } + +.logo-img-wrap { + width: 44px; + height: 44px; + border-radius: 50%; + overflow: hidden; + border: 2px solid transparent; + transition: border-color 0.3s ease; +} +.logo-img-wrap:hover { border-color: var(--brand-gold); } + +/* ══════════════════════════════════════════════════════════ + NAV ITEM WITH DROPDOWN +══════════════════════════════════════════════════════════ */ +.nav-item { + position: relative; +} + +.nav-link { + font-family: var(--font-display); + font-size: 0.72rem; + letter-spacing: 0.2em; + text-transform: uppercase; + color: #ffffff; + text-decoration: none; + padding-bottom: 2px; + border-bottom: 2px solid transparent; + transition: border-color 0.3s ease, color 0.3s ease; + display: inline-flex; + align-items: center; + gap: 5px; + cursor: pointer; + background: none; + border-left: none; + border-right: none; + border-top: none; +} + +.nav-link:hover { + color: var(--brand-gold-light); + border-bottom-color: rgba(212,162,76,0.6); +} + +.nav-link.active { + color: var(--brand-gold-light); + border-bottom-color: var(--brand-gold); + border-bottom-width: 2.5px; + text-shadow: + 0 0 12px rgba(255,211,107,0.9), + 0 0 24px rgba(212,162,76,0.5); + font-weight: 600; + background: rgba(212,162,76,0.12); + border-radius: 4px; + padding: 3px 10px 5px; +} + +.nav-chevron { + transition: transform 0.25s ease; + opacity: 0.75; +} + +.nav-item:hover .nav-chevron { + transform: rotate(180deg); + opacity: 1; +} + +/* DROPDOWN PANEL */ +.nav-dropdown { + position: absolute; + top: calc(100% + 18px); + left: 50%; + transform: translateX(-50%) translateY(-8px); + min-width: 200px; + background: rgba(45, 13, 82, 0.96); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + border: 1px solid rgba(212,162,76,0.2); + border-radius: 8px; + padding: 0.6rem 0; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease, transform 0.25s ease; + box-shadow: 0 16px 40px rgba(0,0,0,0.35); + z-index: 200; +} + +/* Arrow notch */ +.nav-dropdown::before { + content: ''; + position: absolute; + top: -7px; + left: 50%; + transform: translateX(-50%); + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid rgba(212,162,76,0.25); +} + +.nav-dropdown::after { + content: ''; + position: absolute; + top: -6px; + left: 50%; + transform: translateX(-50%); + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid rgba(45,13,82,0.96); +} + +.nav-item:hover .nav-dropdown { + opacity: 1; + pointer-events: auto; + transform: translateX(-50%) translateY(0); +} + +.dropdown-item { + display: flex; + align-items: center; + gap: 0.6rem; + padding: 0.65rem 1.25rem; + font-family: var(--font-sans); + font-size: 0.83rem; + color: rgba(255,255,255,0.78); + text-decoration: none; + transition: background 0.2s ease, color 0.2s ease, padding-left 0.2s ease; + white-space: nowrap; +} + +.dropdown-item:hover { + background: rgba(212,162,76,0.12); + color: var(--brand-gold-light); + padding-left: 1.6rem; +} + +.dropdown-divider { + height: 1px; + background: rgba(255,255,255,0.08); + margin: 0.4rem 0; +} + +/* ══════════════════════════════════════════════════════════ + MOBILE TOGGLE +══════════════════════════════════════════════════════════ */ +.mobile-toggle { + background: none; + border: none; + color: #ffffff; + cursor: pointer; + display: flex; + align-items: center; + padding: 4px; + transition: color 0.3s ease; +} +.mobile-toggle:hover { color: var(--brand-gold-light); } + +/* ══════════════════════════════════════════════════════════ + MOBILE DRAWER +══════════════════════════════════════════════════════════ */ +.mobile-menu { + background: rgba(45, 13, 82, 0.97); + backdrop-filter: blur(16px); + border-bottom: 1px solid rgba(212, 162, 76, 0.2); + padding: 1.5rem; + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.mobile-nav-section { + display: flex; + flex-direction: column; +} + +.mobile-nav-link { + font-family: var(--font-display); + font-size: 0.85rem; + letter-spacing: 0.2em; + text-transform: uppercase; + color: #ffffff; + text-decoration: none; + padding: 0.8rem 0.5rem; + border-bottom: 1px solid rgba(255,255,255,0.07); + transition: color 0.3s ease, padding-left 0.2s ease; + display: block; +} + +.mobile-nav-link:hover { + color: var(--brand-gold-light); + padding-left: 0.75rem; +} + +.mobile-nav-link.active { + color: var(--brand-gold); + padding-left: 0.75rem; + text-shadow: 0 0 10px rgba(255,211,107,0.7); + font-weight: 600; +} + +.mobile-dropdown-items { + display: flex; + flex-direction: column; + padding: 0.25rem 0 0.5rem 1rem; + gap: 0.1rem; + border-bottom: 1px solid rgba(255,255,255,0.07); +} + +.mobile-dropdown-item { + font-family: var(--font-sans); + font-size: 0.82rem; + color: rgba(255,255,255,0.6); + text-decoration: none; + padding: 0.4rem 0.5rem; + transition: color 0.2s ease; +} + +.mobile-dropdown-item:hover { + color: var(--brand-gold-light); +} + +/* ══════════════════════════════════════════════════════════ + FOOTER +══════════════════════════════════════════════════════════ */ +.site-footer { + background: var(--brand-purple-dark); + color: #ffffff; + padding: 4rem 1.5rem; + margin-top: 5rem; +} + +.footer-inner { + max-width: 1280px; + margin: 0 auto; + display: grid; + grid-template-columns: 1fr; + gap: 3rem; + text-align: center; +} + +@media (min-width: 768px) { + .footer-inner { + grid-template-columns: 1fr 1fr 1fr; + text-align: left; + } +} + +.footer-col { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} + +@media (min-width: 768px) { + .footer-col { align-items: flex-start; } +} + +.footer-tagline { + font-family: var(--font-serif); + font-style: italic; + font-size: 1.1rem; + color: rgba(255,255,255,0.7); +} + +.footer-heading { + font-family: var(--font-display); + font-size: 0.7rem; + letter-spacing: 0.25em; + text-transform: uppercase; + color: var(--brand-gold); + margin-bottom: 0.5rem; +} + +.footer-link { + color: rgba(255,255,255,0.75); + font-size: 0.9rem; + text-decoration: none; + transition: color 0.3s ease; +} +.footer-link:hover { color: var(--brand-gold-light); } + +.social-btn { + width: 40px; + height: 40px; + border-radius: 50%; + background: rgba(255,255,255,0.08); + display: flex; + align-items: center; + justify-content: center; + color: #ffffff; + text-decoration: none; + transition: background 0.3s ease, color 0.3s ease; +} +.social-btn:hover { + background: var(--brand-gold); + color: var(--brand-purple-dark); +} + +.footer-copy { + font-size: 0.78rem; + color: rgba(255,255,255,0.4); + margin-top: 1rem; +} diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index 6ff6fca..a586fe8 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -1,310 +1,310 @@ -import { Link, useLocation } from "wouter"; -import { useState, useEffect } from "react"; -import { motion, AnimatePresence } from "framer-motion"; -import AppBar from "@mui/material/AppBar"; -import Toolbar from "@mui/material/Toolbar"; -import Box from "@mui/material/Box"; -import Container from "@mui/material/Container"; -import IconButton from "@mui/material/IconButton"; -import { Menu, X, Instagram, Facebook, Twitter, ChevronDown, Flame, Sparkles, Star } from "lucide-react"; -import { ScrollCandle } from "./ScrollCandle"; -import "./Layout.css"; - -const logoPath = "/opengraph.jpg"; - -// ── Ticker messages ────────────────────────────────────── -const TICKER_ITEMS = [ - { icon: , text: "Free shipping on orders over $50" }, - { icon: , text: "New Collection — Summer Solstice" }, - { icon: , text: "Handpoured in small batches" }, - { icon: , text: "100% Natural Soy Wax" }, - { icon: , text: "Phthalate-free fragrance oils" }, - { icon: , text: "Gift wrapping available at checkout" }, -]; - -// ── Nav structure with dropdowns ───────────────────────── -const NAV_LINKS = [ - { name: "Home", path: "/", dropdown: null }, - { - name: "Products", - path: "/products", - dropdown: [ - { label: "All Collections", path: "/products" }, - null, // divider - { label: "Floral Scents", path: "/products" }, - { label: "Fresh Scents", path: "/products" }, - { label: "Woody Scents", path: "/products" }, - { label: "Sweet Scents", path: "/products" }, - ], - }, - { - name: "About", - path: "/about", - dropdown: [ - { label: "Our Story", path: "/about" }, - { label: "Our Process", path: "/about" }, - { label: "Meet the Maker", path: "/about" }, - ], - }, - { - name: "Contact", - path: "/contact", - dropdown: [ - { label: "Send a Message", path: "/contact" }, - { label: "Wholesale Inquiries", path: "/contact" }, - null, - { label: "Follow on Instagram", path: "/contact" }, - ], - }, -]; - -export function Layout({ children }: { children: React.ReactNode }) { - const [location] = useLocation(); - const [scrolled, setScrolled] = useState(false); - const [mobileMenuOpen, setMobileMenuOpen] = useState(false); - const [mobileOpenSection, setMobileOpenSection] = useState(null); - - useEffect(() => { - const handleScroll = () => setScrolled(window.scrollY > 20); - window.addEventListener("scroll", handleScroll); - return () => window.removeEventListener("scroll", handleScroll); - }, []); - - useEffect(() => { - window.scrollTo(0, 0); - setMobileMenuOpen(false); - setMobileOpenSection(null); - }, [location]); - - // Duplicate ticker items to create seamless loop - const allTickerItems = [...TICKER_ITEMS, ...TICKER_ITEMS]; - - return ( - - - {/* ── Ticker Bar ── */} - -
- {allTickerItems.map((item, i) => ( - - - {item.icon} - {item.text} - - ))} -
-
- - {/* ── Main AppBar ── */} - - - - {/* Logo */} - -
- Mani Candles Co. Logo -
- Mani Candles - - - {/* Desktop Nav */} - - {NAV_LINKS.map((link) => ( -
- - {link.name} - {link.dropdown && } - - - {/* Dropdown */} - {link.dropdown && ( -
- {link.dropdown.map((item, idx) => - item === null ? ( -
- ) : ( - - {item.label} - - ) - )} -
- )} -
- ))} - - - {/* Mobile Toggle */} - setMobileMenuOpen(!mobileMenuOpen)} - > - {mobileMenuOpen ? : } - - - - - {/* Mobile Drawer */} - - {mobileMenuOpen && ( - - {NAV_LINKS.map((link) => ( -
- {link.dropdown ? ( - <> - - - {mobileOpenSection === link.name && ( - - {link.dropdown.map((item, i) => - item === null ? ( -
- ) : ( - - {item.label} - - ) - )} - - )} - - - ) : ( - - {link.name} - - )} -
- ))} -
- )} -
- - - {/* ── Page Content — offset for ticker + appbar ── */} - - - - {children} - - - - - {/* ── Scroll Candle ── */} - - - {/* ── Footer ── */} -
-
-
-
-
- Mani Candles Co. -
- - Mani Candles - -
-

Handmade • Natural • Heartmade

-
- -
-

Explore

- {NAV_LINKS.map((link) => ( - - {link.name} - - ))} -
- -
-

Connect

-
- - - -
-

- © {new Date().getFullYear()} Mani Candles Co. All rights reserved. -

-
-
-
- - ); -} +import { Link, useLocation } from "wouter"; +import { useState, useEffect } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import AppBar from "@mui/material/AppBar"; +import Toolbar from "@mui/material/Toolbar"; +import Box from "@mui/material/Box"; +import Container from "@mui/material/Container"; +import IconButton from "@mui/material/IconButton"; +import { Menu, X, Instagram, Facebook, Twitter, ChevronDown, Flame, Sparkles, Star } from "lucide-react"; +import { ScrollCandle } from "./ScrollCandle"; +import "./Layout.css"; + +const logoPath = "/opengraph.jpg"; + +// ── Ticker messages ────────────────────────────────────── +const TICKER_ITEMS = [ + { icon: , text: "Free shipping on orders over $50" }, + { icon: , text: "New Collection — Summer Solstice" }, + { icon: , text: "Handpoured in small batches" }, + { icon: , text: "100% Natural Soy Wax" }, + { icon: , text: "Phthalate-free fragrance oils" }, + { icon: , text: "Gift wrapping available at checkout" }, +]; + +// ── Nav structure with dropdowns ───────────────────────── +const NAV_LINKS = [ + { name: "Home", path: "/", dropdown: null }, + { + name: "Products", + path: "/products", + dropdown: [ + { label: "All Collections", path: "/products" }, + null, // divider + { label: "Floral Scents", path: "/products" }, + { label: "Fresh Scents", path: "/products" }, + { label: "Woody Scents", path: "/products" }, + { label: "Sweet Scents", path: "/products" }, + ], + }, + { + name: "About", + path: "/about", + dropdown: [ + { label: "Our Story", path: "/about" }, + { label: "Our Process", path: "/about" }, + { label: "Meet the Maker", path: "/about" }, + ], + }, + { + name: "Contact", + path: "/contact", + dropdown: [ + { label: "Send a Message", path: "/contact" }, + { label: "Wholesale Inquiries", path: "/contact" }, + null, + { label: "Follow on Instagram", path: "/contact" }, + ], + }, +]; + +export function Layout({ children }: { children: React.ReactNode }) { + const [location] = useLocation(); + const [scrolled, setScrolled] = useState(false); + const [mobileMenuOpen, setMobileMenuOpen] = useState(false); + const [mobileOpenSection, setMobileOpenSection] = useState(null); + + useEffect(() => { + const handleScroll = () => setScrolled(window.scrollY > 20); + window.addEventListener("scroll", handleScroll); + return () => window.removeEventListener("scroll", handleScroll); + }, []); + + useEffect(() => { + window.scrollTo(0, 0); + setMobileMenuOpen(false); + setMobileOpenSection(null); + }, [location]); + + // Duplicate ticker items to create seamless loop + const allTickerItems = [...TICKER_ITEMS, ...TICKER_ITEMS]; + + return ( + + + {/* ── Ticker Bar ── */} + +
+ {allTickerItems.map((item, i) => ( + + + {item.icon} + {item.text} + + ))} +
+
+ + {/* ── Main AppBar ── */} + + + + {/* Logo */} + +
+ Mani Candles Co. Logo +
+ Mani Candles + + + {/* Desktop Nav */} + + {NAV_LINKS.map((link) => ( +
+ + {link.name} + {link.dropdown && } + + + {/* Dropdown */} + {link.dropdown && ( +
+ {link.dropdown.map((item, idx) => + item === null ? ( +
+ ) : ( + + {item.label} + + ) + )} +
+ )} +
+ ))} + + + {/* Mobile Toggle */} + setMobileMenuOpen(!mobileMenuOpen)} + > + {mobileMenuOpen ? : } + + + + + {/* Mobile Drawer */} + + {mobileMenuOpen && ( + + {NAV_LINKS.map((link) => ( +
+ {link.dropdown ? ( + <> + + + {mobileOpenSection === link.name && ( + + {link.dropdown.map((item, i) => + item === null ? ( +
+ ) : ( + + {item.label} + + ) + )} + + )} + + + ) : ( + + {link.name} + + )} +
+ ))} +
+ )} +
+ + + {/* ── Page Content — offset for ticker + appbar ── */} + + + + {children} + + + + + {/* ── Scroll Candle ── */} + + + {/* ── Footer ── */} +
+
+
+
+
+ Mani Candles Co. +
+ + Mani Candles + +
+

Handmade • Natural • Heartmade

+
+ +
+

Explore

+ {NAV_LINKS.map((link) => ( + + {link.name} + + ))} +
+ +
+

Connect

+
+ + + +
+

+ © {new Date().getFullYear()} Mani Candles Co. All rights reserved. +

+
+
+
+ + ); +} diff --git a/src/components/ScrollCandle.css b/src/components/ScrollCandle.css index 8f03063..5444e66 100644 --- a/src/components/ScrollCandle.css +++ b/src/components/ScrollCandle.css @@ -1,291 +1,291 @@ -/* ─── ScrollCandle.css ───────────────────────────────────── */ - -.scroll-candle-wrap { - position: fixed; - right: 28px; - bottom: 0px; - z-index: 999; - display: flex; - flex-direction: column; - align-items: center; - pointer-events: none; - filter: drop-shadow(0 0 18px rgba(255, 160, 40, 0.35)); -} - -/* ── FLAME SYSTEM ─────────────────────────────────── */ -.candle-flame-wrap { - position: relative; - display: flex; - flex-direction: column; - align-items: center; - margin-bottom: -2px; -} - -/* Outer glow halo */ -.flame-glow { - position: absolute; - bottom: 0; - left: 50%; - transform: translateX(-50%); - width: 48px; - height: 48px; - border-radius: 50%; - background: radial-gradient(circle, rgba(255, 200, 50, 0.45) 0%, transparent 70%); - animation: glow-pulse 1.8s ease-in-out infinite alternate; - z-index: 0; -} - -@keyframes glow-pulse { - 0% { - transform: translateX(-50%) scale(1); - opacity: 0.7; - } - - 100% { - transform: translateX(-50%) scale(1.35); - opacity: 1; - } -} - -/* Flame outer — large orange teardrop */ -.flame-outer { - position: relative; - z-index: 2; - width: 18px; - height: 34px; - background: linear-gradient(to top, #ff6a00, #ffaa00, #ffe066); - border-radius: 50% 50% 30% 30% / 60% 60% 40% 40%; - transform-origin: bottom center; - animation: flicker-outer 0.9s ease-in-out infinite alternate; - box-shadow: - 0 0 8px 3px rgba(255, 140, 0, 0.6), - 0 0 18px 6px rgba(255, 100, 0, 0.4); -} - -@keyframes flicker-outer { - 0% { - transform: scaleX(1) scaleY(1) rotate(-2deg); - } - - 25% { - transform: scaleX(0.88) scaleY(1.05) rotate(2deg); - } - - 50% { - transform: scaleX(1.05) scaleY(0.95) rotate(-1deg); - } - - 75% { - transform: scaleX(0.92) scaleY(1.08) rotate(3deg); - } - - 100% { - transform: scaleX(1.02) scaleY(1.02) rotate(-2deg); - } -} - -/* Flame inner — bright white-yellow core */ -.flame-inner { - position: absolute; - bottom: 4px; - left: 50%; - transform: translateX(-50%); - z-index: 3; - width: 8px; - height: 18px; - background: linear-gradient(to top, #fff8c5, #fff, rgba(255, 255, 255, 0)); - border-radius: 50% 50% 30% 30% / 60% 60% 40% 40%; - animation: flicker-inner 0.7s ease-in-out infinite alternate; - opacity: 0.9; -} - -@keyframes flicker-inner { - 0% { - transform: translateX(-50%) scaleX(1) scaleY(1); - } - - 50% { - transform: translateX(-50%) scaleX(0.85) scaleY(1.1); - } - - 100% { - transform: translateX(-50%) scaleX(1.1) scaleY(0.9); - } -} - -/* ── SMOKE PARTICLES ─────────────────────────────── */ -.smoke-wrap { - position: absolute; - top: -18px; - left: 50%; - transform: translateX(-50%); - width: 20px; - height: 20px; - pointer-events: none; - z-index: 4; -} - -.smoke-particle { - position: absolute; - bottom: 0; - left: 50%; - width: 4px; - height: 4px; - border-radius: 50%; - background: rgba(200, 180, 220, 0.45); - transform: translateX(-50%); - animation: smoke-rise 2.4s ease-out infinite; - opacity: 0; -} - -.smoke-particle:nth-child(2) { - animation-delay: 0.8s; - left: 40%; -} - -.smoke-particle:nth-child(3) { - animation-delay: 1.6s; - left: 60%; -} - -@keyframes smoke-rise { - 0% { - transform: translateX(-50%) translateY(0) scale(0.6); - opacity: 0; - } - - 20% { - opacity: 0.5; - } - - 100% { - transform: translateX(-50%) translateY(-22px) scale(2); - opacity: 0; - } -} - -/* ── WICK ──────────────────────────────────────────── */ -.candle-wick { - width: 2px; - height: 8px; - background: linear-gradient(to bottom, #3a2000, #1a0f00); - border-radius: 1px; - position: relative; - z-index: 2; - margin-bottom: -1px; -} - -/* ── CANDLE BODY ──────────────────────────────────── */ -.candle-body { - position: relative; - width: 22px; - background: linear-gradient(to right, - #e8dcc8 0%, - #fdf6e3 25%, - #fff9f0 50%, - #fdf6e3 75%, - #d9cbb5 100%); - border-radius: 3px 3px 4px 4px; - transition: height 0.18s linear; - box-shadow: - inset -3px 0 6px rgba(0, 0, 0, 0.1), - inset 3px 0 4px rgba(255, 255, 255, 0.4); - overflow: visible; -} - -/* Candle top melted rim */ -.candle-body::before { - content: ''; - position: absolute; - top: -3px; - left: -2px; - right: -2px; - height: 6px; - background: radial-gradient(ellipse at center, #ffe8b0 0%, #e8d5a0 100%); - border-radius: 50%; - z-index: 1; -} - -/* ── WAX DRIPS ──────────────────────────────────────── */ -.wax-drip { - position: absolute; - top: 2px; - width: 5px; - background: linear-gradient(to bottom, rgba(253, 246, 227, 0.95), rgba(232, 220, 200, 0.6)); - border-radius: 0 0 4px 4px; - animation: drip-grow 4s ease-in-out infinite; -} - -.wax-drip-1 { - left: -3px; - height: 14px; - animation-delay: 0s; - animation-duration: 4.5s; -} - -.wax-drip-2 { - right: -3px; - height: 10px; - animation-delay: 1.2s; - animation-duration: 3.8s; -} - -.wax-drip-3 { - left: 2px; - height: 18px; - animation-delay: 2.5s; - animation-duration: 5.2s; -} - -@keyframes drip-grow { - 0% { - height: 6px; - opacity: 0.7; - } - - 60% { - height: 20px; - opacity: 1; - } - - 100% { - height: 6px; - opacity: 0.7; - } -} - -/* ── CANDLE BASE / HOLDER ────────────────────────── */ -.candle-base { - width: 32px; - height: 10px; - background: linear-gradient(to bottom, #c8a96e, #a07840); - border-radius: 3px 3px 6px 6px; - box-shadow: - 0 3px 8px rgba(0, 0, 0, 0.3), - inset 0 1px 2px rgba(255, 200, 100, 0.4); - position: relative; -} - -/* Holder shine */ -.candle-base::after { - content: ''; - position: absolute; - top: 2px; - left: 5px; - width: 8px; - height: 3px; - background: rgba(255, 220, 140, 0.4); - border-radius: 50%; -} - -/* ── SCROLL LABEL ───────────────────────────────── */ -.candle-scroll-label { - margin-top: 6px; - font-family: var(--font-script); - font-size: 0.68rem; - color: rgba(212, 162, 76, 0.7); - letter-spacing: 0.05em; - white-space: nowrap; - text-align: center; - transition: opacity 0.3s ease; +/* ─── ScrollCandle.css ───────────────────────────────────── */ + +.scroll-candle-wrap { + position: fixed; + right: 28px; + bottom: 0px; + z-index: 999; + display: flex; + flex-direction: column; + align-items: center; + pointer-events: none; + filter: drop-shadow(0 0 18px rgba(255, 160, 40, 0.35)); +} + +/* ── FLAME SYSTEM ─────────────────────────────────── */ +.candle-flame-wrap { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: -2px; +} + +/* Outer glow halo */ +.flame-glow { + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%); + width: 48px; + height: 48px; + border-radius: 50%; + background: radial-gradient(circle, rgba(255, 200, 50, 0.45) 0%, transparent 70%); + animation: glow-pulse 1.8s ease-in-out infinite alternate; + z-index: 0; +} + +@keyframes glow-pulse { + 0% { + transform: translateX(-50%) scale(1); + opacity: 0.7; + } + + 100% { + transform: translateX(-50%) scale(1.35); + opacity: 1; + } +} + +/* Flame outer — large orange teardrop */ +.flame-outer { + position: relative; + z-index: 2; + width: 18px; + height: 34px; + background: linear-gradient(to top, #ff6a00, #ffaa00, #ffe066); + border-radius: 50% 50% 30% 30% / 60% 60% 40% 40%; + transform-origin: bottom center; + animation: flicker-outer 0.9s ease-in-out infinite alternate; + box-shadow: + 0 0 8px 3px rgba(255, 140, 0, 0.6), + 0 0 18px 6px rgba(255, 100, 0, 0.4); +} + +@keyframes flicker-outer { + 0% { + transform: scaleX(1) scaleY(1) rotate(-2deg); + } + + 25% { + transform: scaleX(0.88) scaleY(1.05) rotate(2deg); + } + + 50% { + transform: scaleX(1.05) scaleY(0.95) rotate(-1deg); + } + + 75% { + transform: scaleX(0.92) scaleY(1.08) rotate(3deg); + } + + 100% { + transform: scaleX(1.02) scaleY(1.02) rotate(-2deg); + } +} + +/* Flame inner — bright white-yellow core */ +.flame-inner { + position: absolute; + bottom: 4px; + left: 50%; + transform: translateX(-50%); + z-index: 3; + width: 8px; + height: 18px; + background: linear-gradient(to top, #fff8c5, #fff, rgba(255, 255, 255, 0)); + border-radius: 50% 50% 30% 30% / 60% 60% 40% 40%; + animation: flicker-inner 0.7s ease-in-out infinite alternate; + opacity: 0.9; +} + +@keyframes flicker-inner { + 0% { + transform: translateX(-50%) scaleX(1) scaleY(1); + } + + 50% { + transform: translateX(-50%) scaleX(0.85) scaleY(1.1); + } + + 100% { + transform: translateX(-50%) scaleX(1.1) scaleY(0.9); + } +} + +/* ── SMOKE PARTICLES ─────────────────────────────── */ +.smoke-wrap { + position: absolute; + top: -18px; + left: 50%; + transform: translateX(-50%); + width: 20px; + height: 20px; + pointer-events: none; + z-index: 4; +} + +.smoke-particle { + position: absolute; + bottom: 0; + left: 50%; + width: 4px; + height: 4px; + border-radius: 50%; + background: rgba(200, 180, 220, 0.45); + transform: translateX(-50%); + animation: smoke-rise 2.4s ease-out infinite; + opacity: 0; +} + +.smoke-particle:nth-child(2) { + animation-delay: 0.8s; + left: 40%; +} + +.smoke-particle:nth-child(3) { + animation-delay: 1.6s; + left: 60%; +} + +@keyframes smoke-rise { + 0% { + transform: translateX(-50%) translateY(0) scale(0.6); + opacity: 0; + } + + 20% { + opacity: 0.5; + } + + 100% { + transform: translateX(-50%) translateY(-22px) scale(2); + opacity: 0; + } +} + +/* ── WICK ──────────────────────────────────────────── */ +.candle-wick { + width: 2px; + height: 8px; + background: linear-gradient(to bottom, #3a2000, #1a0f00); + border-radius: 1px; + position: relative; + z-index: 2; + margin-bottom: -1px; +} + +/* ── CANDLE BODY ──────────────────────────────────── */ +.candle-body { + position: relative; + width: 22px; + background: linear-gradient(to right, + #e8dcc8 0%, + #fdf6e3 25%, + #fff9f0 50%, + #fdf6e3 75%, + #d9cbb5 100%); + border-radius: 3px 3px 4px 4px; + transition: height 0.18s linear; + box-shadow: + inset -3px 0 6px rgba(0, 0, 0, 0.1), + inset 3px 0 4px rgba(255, 255, 255, 0.4); + overflow: visible; +} + +/* Candle top melted rim */ +.candle-body::before { + content: ''; + position: absolute; + top: -3px; + left: -2px; + right: -2px; + height: 6px; + background: radial-gradient(ellipse at center, #ffe8b0 0%, #e8d5a0 100%); + border-radius: 50%; + z-index: 1; +} + +/* ── WAX DRIPS ──────────────────────────────────────── */ +.wax-drip { + position: absolute; + top: 2px; + width: 5px; + background: linear-gradient(to bottom, rgba(253, 246, 227, 0.95), rgba(232, 220, 200, 0.6)); + border-radius: 0 0 4px 4px; + animation: drip-grow 4s ease-in-out infinite; +} + +.wax-drip-1 { + left: -3px; + height: 14px; + animation-delay: 0s; + animation-duration: 4.5s; +} + +.wax-drip-2 { + right: -3px; + height: 10px; + animation-delay: 1.2s; + animation-duration: 3.8s; +} + +.wax-drip-3 { + left: 2px; + height: 18px; + animation-delay: 2.5s; + animation-duration: 5.2s; +} + +@keyframes drip-grow { + 0% { + height: 6px; + opacity: 0.7; + } + + 60% { + height: 20px; + opacity: 1; + } + + 100% { + height: 6px; + opacity: 0.7; + } +} + +/* ── CANDLE BASE / HOLDER ────────────────────────── */ +.candle-base { + width: 32px; + height: 10px; + background: linear-gradient(to bottom, #c8a96e, #a07840); + border-radius: 3px 3px 6px 6px; + box-shadow: + 0 3px 8px rgba(0, 0, 0, 0.3), + inset 0 1px 2px rgba(255, 200, 100, 0.4); + position: relative; +} + +/* Holder shine */ +.candle-base::after { + content: ''; + position: absolute; + top: 2px; + left: 5px; + width: 8px; + height: 3px; + background: rgba(255, 220, 140, 0.4); + border-radius: 50%; +} + +/* ── SCROLL LABEL ───────────────────────────────── */ +.candle-scroll-label { + margin-top: 6px; + font-family: var(--font-script); + font-size: 0.68rem; + color: rgba(212, 162, 76, 0.7); + letter-spacing: 0.05em; + white-space: nowrap; + text-align: center; + transition: opacity 0.3s ease; } \ No newline at end of file diff --git a/src/components/ScrollCandle.tsx b/src/components/ScrollCandle.tsx index 1ae133a..a9cc411 100644 --- a/src/components/ScrollCandle.tsx +++ b/src/components/ScrollCandle.tsx @@ -1,99 +1,99 @@ -import { useEffect, useState } from "react"; -import "./ScrollCandle.css"; - -// Space taken by flame + wick + base + label + bottom offset + header (ticker 36 + AppBar 76) + safety gap -const NON_BODY_HEIGHT = 70 + 8 + 10 + 24 + 40 + 112 + 16; -const CANDLE_MIN_HEIGHT = 14; // px — almost fully melted -// -export function ScrollCandle() { - const [maxHeight, setMaxHeight] = useState( - () => Math.max(200, window.innerHeight - NON_BODY_HEIGHT) - ); - const [candleHeight, setCandleHeight] = useState( - () => Math.max(200, window.innerHeight - NON_BODY_HEIGHT) - ); - const [scrollPct, setScrollPct] = useState(0); - - // Recalculate on resize - useEffect(() => { - const onResize = () => { - const newMax = Math.max(200, window.innerHeight - NON_BODY_HEIGHT); - setMaxHeight(newMax); - }; - window.addEventListener("resize", onResize); - return () => window.removeEventListener("resize", onResize); - }, []); - - useEffect(() => { - const handleScroll = () => { - const scrollTop = window.scrollY; - const docHeight = document.documentElement.scrollHeight - window.innerHeight; - const pct = docHeight > 0 ? Math.min(scrollTop / docHeight, 1) : 0; - - setScrollPct(pct); - setCandleHeight( - Math.max(CANDLE_MIN_HEIGHT, maxHeight - pct * (maxHeight - CANDLE_MIN_HEIGHT)) - ); - }; - - window.addEventListener("scroll", handleScroll, { passive: true }); - return () => window.removeEventListener("scroll", handleScroll); - }, [maxHeight]); - - // Flame shrinks slightly as candle melts - const flameScale = 0.6 + (candleHeight / maxHeight) * 0.4; - // Label changes as candle melts - const label = - scrollPct < 0.15 ? "just lit" : - scrollPct < 0.45 ? "burning..." : - scrollPct < 0.75 ? "melting..." : - scrollPct < 0.92 ? "almost gone" : - "★ keep scrolling"; - - return ( -