This commit is contained in:
2026-03-29 10:26:38 -05:00
parent 05d4f6e78b
commit b1c99893a6
1628 changed files with 67782 additions and 60143 deletions

View File

@@ -1,349 +1,349 @@
'use client'
import { useRef, useState } from 'react'
import { useLang } from '@/context/LangContext'
export default function BrownLeaf() {
const { t } = useLang()
const bl = t.brownLeaf
const [sliderVal, setSliderVal] = useState(50)
const containerRef = useRef<HTMLDivElement>(null)
const proofs = [
{
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#e07a50" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z" />
</svg>
),
title: bl.proof1title,
desc: bl.proof1desc,
color: '#e07a50',
},
{
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#56a074" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="M7 16.3c2.2 0 4-1.83 4-4.05 0-1.16-.57-2.26-1.71-3.19S7.29 6.75 7 5.3c-.29 1.45-1.14 2.84-2.29 3.76S3 11.1 3 12.25c0 2.22 1.8 4.05 4 4.05z" />
<path d="M12.56 6.6A10.97 10.97 0 0 0 14 3.02c.5 2.5 2 4.9 4 6.5s3 3.5 3 5.5a6.98 6.98 0 0 1-11.91 4.97" />
</svg>
),
title: bl.proof2title,
desc: bl.proof2desc,
color: '#56a074',
},
{
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#3d7a56" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="M9 3h6l-1 7H10z" />
<path d="M12 10v4" />
<path d="M8 21v-4a4 4 0 0 1 8 0v4" />
<path d="M6 21h12" />
<path d="M4 10h3" />
<path d="M17 10h3" />
</svg>
),
title: bl.proof3title,
desc: bl.proof3desc,
color: '#3d7a56',
},
]
return (
<section className="brownleaf" id="brownleaf" aria-labelledby="bl-heading">
<div className="container">
{/* Header */}
<header className="bl-header reveal">
<p className="tag">{bl.tag}</p>
<h2 id="bl-heading">
{bl.headline}<br />
<em>{bl.sub}</em>
</h2>
<p className="bl-desc">{bl.desc}</p>
</header>
{/* Before / After Slider */}
<div className="bl-slider-wrap reveal delay-1" ref={containerRef}>
<div
className="bl-slider-track"
style={{ '--pos': `${sliderVal}%` } as React.CSSProperties}
aria-label={bl.sliderLabel}
>
{/* BEFORE brown/unhealthy (always visible) */}
<div className="bl-panel bl-before" aria-hidden="true">
<div className="bl-panel-img bl-before-img" />
<div className="bl-panel-overlay bl-before-overlay" />
<span className="bl-label bl-label-before">{bl.before}</span>
</div>
{/* AFTER healthy plant (clips from right) */}
<div
className="bl-panel bl-after"
style={{ clipPath: `inset(0 0 0 ${sliderVal}%)` }}
aria-hidden="true"
>
<div className="bl-panel-img bl-after-img" />
<div className="bl-panel-overlay bl-after-overlay" />
<span className="bl-label bl-label-after">{bl.after}</span>
</div>
{/* Divider line */}
<div
className="bl-divider"
style={{ left: `${sliderVal}%` }}
aria-hidden="true"
>
<div className="bl-divider-handle">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
<path d="M9 18l-6-6 6-6" />
<path d="M15 6l6 6-6 6" />
</svg>
</div>
</div>
{/* Range input for accessibility & interaction */}
<input
type="range"
min={0}
max={100}
value={sliderVal}
onChange={e => setSliderVal(Number(e.target.value))}
className="bl-range"
aria-label={bl.sliderLabel}
/>
</div>
{/* Scan badge overlay */}
<div className="bl-scan-badge">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="M9.5 2a2.5 2.5 0 0 1 5 0v.5a2 2 0 0 0 1.5 1.94V6a2 2 0 0 0 2 2h.5a2.5 2.5 0 0 1 0 5H18a2 2 0 0 0-2 2v.56A2.5 2.5 0 0 1 14.5 22h-5A2.5 2.5 0 0 1 7 19.56V18a2 2 0 0 0-2-2h-.5a2.5 2.5 0 0 1 0-5H5a2 2 0 0 0 2-2V4.44A2 2 0 0 0 8.5 2.5z" />
<circle cx="12" cy="12" r="2" />
</svg>
Botanical Intelligence
</div>
</div>
{/* Success Story Cards */}
<div className="bl-proofs">
{proofs.map((p, i) => (
<div className={`bl-proof reveal delay-${i + 1}`} key={p.title}>
<div className="bl-proof-icon" style={{ background: `${p.color}18`, border: `1px solid ${p.color}30` }}>
{p.icon}
</div>
<div>
<h4 className="bl-proof-title">{p.title}</h4>
<p className="bl-proof-desc">{p.desc}</p>
</div>
</div>
))}
</div>
</div>
<style jsx>{`
.brownleaf {
padding: var(--s16) 0;
background: var(--dark);
position: relative;
overflow: hidden;
}
.brownleaf::before {
content: '';
position: absolute;
width: 600px;
height: 600px;
background: radial-gradient(circle, rgba(224,122,80,0.08) 0%, transparent 70%);
top: -100px;
left: -200px;
pointer-events: none;
}
.bl-header {
text-align: center;
max-width: 640px;
margin: 0 auto var(--s12);
}
.bl-header h2 {
color: var(--cream);
margin-bottom: var(--s3);
}
.bl-header h2 em {
display: block;
font-style: italic;
color: var(--green-light);
}
.bl-desc {
color: var(--text-light);
font-size: 1rem;
line-height: 1.75;
}
/* Slider */
.bl-slider-wrap {
position: relative;
max-width: 800px;
margin: 0 auto var(--s12);
}
.bl-slider-track {
position: relative;
border-radius: var(--r-xl);
overflow: hidden;
aspect-ratio: 16/9;
user-select: none;
box-shadow: 0 30px 80px rgba(0,0,0,0.4), 0 0 0 1px rgba(244,241,232,0.06);
cursor: col-resize;
}
.bl-panel {
position: absolute;
inset: 0;
}
.bl-panel-img {
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
}
.bl-before-img {
background-image: url(/unhealthy-plant.png);
}
.bl-after-img {
background-image: url(/plant-collection.png);
filter: saturate(1.3) brightness(1.05);
}
.bl-panel-overlay {
position: absolute;
inset: 0;
}
.bl-before-overlay {
background: linear-gradient(135deg, rgba(80,40,10,0.35) 0%, transparent 60%);
}
.bl-after-overlay {
background: linear-gradient(135deg, rgba(13,40,20,0.2) 0%, transparent 60%);
}
.bl-label {
position: absolute;
bottom: 1.2rem;
font-size: 0.7rem;
font-weight: 800;
letter-spacing: 0.15em;
text-transform: uppercase;
color: rgba(244,241,232,0.9);
background: rgba(0,0,0,0.45);
backdrop-filter: blur(8px);
border-radius: 999px;
padding: 0.3rem 0.8rem;
border: 1px solid rgba(244,241,232,0.12);
}
.bl-label-before { left: 1.2rem; }
.bl-label-after { right: 1.2rem; }
/* Divider */
.bl-divider {
position: absolute;
top: 0;
bottom: 0;
width: 2px;
background: rgba(244,241,232,0.7);
transform: translateX(-50%);
pointer-events: none;
z-index: 10;
}
.bl-divider-handle {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 44px;
height: 44px;
border-radius: 50%;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
color: var(--dark);
}
/* Range input */
.bl-range {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: col-resize;
z-index: 20;
margin: 0;
}
/* Scan badge */
.bl-scan-badge {
position: absolute;
top: 1.2rem;
right: 1.2rem;
display: flex;
align-items: center;
gap: 0.4rem;
background: rgba(19,31,22,0.85);
backdrop-filter: blur(12px);
border: 1px solid rgba(86,160,116,0.3);
border-radius: var(--r-md);
padding: 0.5rem 0.9rem;
color: var(--green-light);
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.06em;
z-index: 5;
pointer-events: none;
}
/* Proof cards */
.bl-proofs {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--s3);
max-width: 800px;
margin: 0 auto;
}
.bl-proof {
display: flex;
align-items: flex-start;
gap: var(--s2);
background: rgba(244,241,232,0.04);
border: 1px solid rgba(244,241,232,0.08);
border-radius: var(--r-lg);
padding: var(--s3);
}
.bl-proof-icon {
width: 44px;
height: 44px;
min-width: 44px;
border-radius: var(--r-sm);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.3rem;
}
.bl-proof-title {
font-family: var(--body);
font-size: 0.82rem;
font-weight: 700;
color: var(--cream);
margin-bottom: 3px;
}
.bl-proof-desc {
font-size: 0.75rem;
color: var(--text-light);
line-height: 1.5;
}
@media (max-width: 768px) {
.bl-proofs {
grid-template-columns: 1fr;
}
}
`}</style>
</section>
)
}
'use client'
import { useRef, useState } from 'react'
import { useLang } from '@/context/LangContext'
export default function BrownLeaf() {
const { t } = useLang()
const bl = t.brownLeaf
const [sliderVal, setSliderVal] = useState(50)
const containerRef = useRef<HTMLDivElement>(null)
const proofs = [
{
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#e07a50" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z" />
</svg>
),
title: bl.proof1title,
desc: bl.proof1desc,
color: '#e07a50',
},
{
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#56a074" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="M7 16.3c2.2 0 4-1.83 4-4.05 0-1.16-.57-2.26-1.71-3.19S7.29 6.75 7 5.3c-.29 1.45-1.14 2.84-2.29 3.76S3 11.1 3 12.25c0 2.22 1.8 4.05 4 4.05z" />
<path d="M12.56 6.6A10.97 10.97 0 0 0 14 3.02c.5 2.5 2 4.9 4 6.5s3 3.5 3 5.5a6.98 6.98 0 0 1-11.91 4.97" />
</svg>
),
title: bl.proof2title,
desc: bl.proof2desc,
color: '#56a074',
},
{
icon: (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#3d7a56" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="M9 3h6l-1 7H10z" />
<path d="M12 10v4" />
<path d="M8 21v-4a4 4 0 0 1 8 0v4" />
<path d="M6 21h12" />
<path d="M4 10h3" />
<path d="M17 10h3" />
</svg>
),
title: bl.proof3title,
desc: bl.proof3desc,
color: '#3d7a56',
},
]
return (
<section className="brownleaf" id="brownleaf" aria-labelledby="bl-heading">
<div className="container">
{/* Header */}
<header className="bl-header reveal">
<p className="tag">{bl.tag}</p>
<h2 id="bl-heading">
{bl.headline}<br />
<em>{bl.sub}</em>
</h2>
<p className="bl-desc">{bl.desc}</p>
</header>
{/* Before / After Slider */}
<div className="bl-slider-wrap reveal delay-1" ref={containerRef}>
<div
className="bl-slider-track"
style={{ '--pos': `${sliderVal}%` } as React.CSSProperties}
aria-label={bl.sliderLabel}
>
{/* BEFORE brown/unhealthy (always visible) */}
<div className="bl-panel bl-before" aria-hidden="true">
<div className="bl-panel-img bl-before-img" />
<div className="bl-panel-overlay bl-before-overlay" />
<span className="bl-label bl-label-before">{bl.before}</span>
</div>
{/* AFTER healthy plant (clips from right) */}
<div
className="bl-panel bl-after"
style={{ clipPath: `inset(0 0 0 ${sliderVal}%)` }}
aria-hidden="true"
>
<div className="bl-panel-img bl-after-img" />
<div className="bl-panel-overlay bl-after-overlay" />
<span className="bl-label bl-label-after">{bl.after}</span>
</div>
{/* Divider line */}
<div
className="bl-divider"
style={{ left: `${sliderVal}%` }}
aria-hidden="true"
>
<div className="bl-divider-handle">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
<path d="M9 18l-6-6 6-6" />
<path d="M15 6l6 6-6 6" />
</svg>
</div>
</div>
{/* Range input for accessibility & interaction */}
<input
type="range"
min={0}
max={100}
value={sliderVal}
onChange={e => setSliderVal(Number(e.target.value))}
className="bl-range"
aria-label={bl.sliderLabel}
/>
</div>
{/* Scan badge overlay */}
<div className="bl-scan-badge">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="M9.5 2a2.5 2.5 0 0 1 5 0v.5a2 2 0 0 0 1.5 1.94V6a2 2 0 0 0 2 2h.5a2.5 2.5 0 0 1 0 5H18a2 2 0 0 0-2 2v.56A2.5 2.5 0 0 1 14.5 22h-5A2.5 2.5 0 0 1 7 19.56V18a2 2 0 0 0-2-2h-.5a2.5 2.5 0 0 1 0-5H5a2 2 0 0 0 2-2V4.44A2 2 0 0 0 8.5 2.5z" />
<circle cx="12" cy="12" r="2" />
</svg>
Botanical Intelligence
</div>
</div>
{/* Success Story Cards */}
<div className="bl-proofs">
{proofs.map((p, i) => (
<div className={`bl-proof reveal delay-${i + 1}`} key={p.title}>
<div className="bl-proof-icon" style={{ background: `${p.color}18`, border: `1px solid ${p.color}30` }}>
{p.icon}
</div>
<div>
<h4 className="bl-proof-title">{p.title}</h4>
<p className="bl-proof-desc">{p.desc}</p>
</div>
</div>
))}
</div>
</div>
<style jsx>{`
.brownleaf {
padding: var(--s16) 0;
background: var(--dark);
position: relative;
overflow: hidden;
}
.brownleaf::before {
content: '';
position: absolute;
width: 600px;
height: 600px;
background: radial-gradient(circle, rgba(224,122,80,0.08) 0%, transparent 70%);
top: -100px;
left: -200px;
pointer-events: none;
}
.bl-header {
text-align: center;
max-width: 640px;
margin: 0 auto var(--s12);
}
.bl-header h2 {
color: var(--cream);
margin-bottom: var(--s3);
}
.bl-header h2 em {
display: block;
font-style: italic;
color: var(--green-light);
}
.bl-desc {
color: var(--text-light);
font-size: 1rem;
line-height: 1.75;
}
/* Slider */
.bl-slider-wrap {
position: relative;
max-width: 800px;
margin: 0 auto var(--s12);
}
.bl-slider-track {
position: relative;
border-radius: var(--r-xl);
overflow: hidden;
aspect-ratio: 16/9;
user-select: none;
box-shadow: 0 30px 80px rgba(0,0,0,0.4), 0 0 0 1px rgba(244,241,232,0.06);
cursor: col-resize;
}
.bl-panel {
position: absolute;
inset: 0;
}
.bl-panel-img {
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
}
.bl-before-img {
background-image: url(/unhealthy-plant.png);
}
.bl-after-img {
background-image: url(/plant-collection.png);
filter: saturate(1.3) brightness(1.05);
}
.bl-panel-overlay {
position: absolute;
inset: 0;
}
.bl-before-overlay {
background: linear-gradient(135deg, rgba(80,40,10,0.35) 0%, transparent 60%);
}
.bl-after-overlay {
background: linear-gradient(135deg, rgba(13,40,20,0.2) 0%, transparent 60%);
}
.bl-label {
position: absolute;
bottom: 1.2rem;
font-size: 0.7rem;
font-weight: 800;
letter-spacing: 0.15em;
text-transform: uppercase;
color: rgba(244,241,232,0.9);
background: rgba(0,0,0,0.45);
backdrop-filter: blur(8px);
border-radius: 999px;
padding: 0.3rem 0.8rem;
border: 1px solid rgba(244,241,232,0.12);
}
.bl-label-before { left: 1.2rem; }
.bl-label-after { right: 1.2rem; }
/* Divider */
.bl-divider {
position: absolute;
top: 0;
bottom: 0;
width: 2px;
background: rgba(244,241,232,0.7);
transform: translateX(-50%);
pointer-events: none;
z-index: 10;
}
.bl-divider-handle {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 44px;
height: 44px;
border-radius: 50%;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
color: var(--dark);
}
/* Range input */
.bl-range {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: col-resize;
z-index: 20;
margin: 0;
}
/* Scan badge */
.bl-scan-badge {
position: absolute;
top: 1.2rem;
right: 1.2rem;
display: flex;
align-items: center;
gap: 0.4rem;
background: rgba(19,31,22,0.85);
backdrop-filter: blur(12px);
border: 1px solid rgba(86,160,116,0.3);
border-radius: var(--r-md);
padding: 0.5rem 0.9rem;
color: var(--green-light);
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.06em;
z-index: 5;
pointer-events: none;
}
/* Proof cards */
.bl-proofs {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--s3);
max-width: 800px;
margin: 0 auto;
}
.bl-proof {
display: flex;
align-items: flex-start;
gap: var(--s2);
background: rgba(244,241,232,0.04);
border: 1px solid rgba(244,241,232,0.08);
border-radius: var(--r-lg);
padding: var(--s3);
}
.bl-proof-icon {
width: 44px;
height: 44px;
min-width: 44px;
border-radius: var(--r-sm);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.3rem;
}
.bl-proof-title {
font-family: var(--body);
font-size: 0.82rem;
font-weight: 700;
color: var(--cream);
margin-bottom: 3px;
}
.bl-proof-desc {
font-size: 0.75rem;
color: var(--text-light);
line-height: 1.5;
}
@media (max-width: 768px) {
.bl-proofs {
grid-template-columns: 1fr;
}
}
`}</style>
</section>
)
}