feat: Awwwards transformation Phases 1-6

Phase 1 — Design System:
- Glassmorphism tokens (--glass-bg, --glass-border, --blur-glass)
- Gradient tokens (--hds-gradient-hero, --hds-gradient-section)
- Motion tokens (--ease-spring, --ease-out-expo)
- .glass-card component class with hover uplift + mouse-tracking glow
- .noise-overlay: SVG feTurbulence texture at 0.025 opacity
- Buttons with spring easing, prefers-reduced-motion support

Phase 2 — Preloader + Hero:
- Preloader.astro: vanilla JS logo fade-in + loading bar + slide-up
- Uses sessionStorage to skip on repeat visits
- Hero.astro: full-bleed 100dvh, GSAP timeline, glass ring decoration
- Parallax floating SVG shapes (sine yoyo animation)
- i18n: hero.scrollDown key

Phase 3 — 'Por qué elegirnos' Bento Grid:
- DifferenceCards.astro: asymmetric 3-column bento grid
- Glass cards with mouse-tracking glow (--mouse-x/--mouse-y)
- GSAP ScrollTrigger stagger reveal (opacity 0→1, y: 40→0)

Phase 4 — Pricing + Process:
- planes.astro: 5 visible + 4 in details accordion
- Empresarial as hero card, price annual only (no toggle)
- ProcessSteps.astro: timeline + ScrollTrigger progress bar

Phase 5 — Global Polish:
- LenisScroll.astro: smooth scroll (duration 1.2, cubic easing)
- GSAP ticker sync, noise overlay in BaseLayout

Phase 6 — Deploy:
- deploy.sh: auto-detects repo path, auto-builds if stale
- Relative paths instead of hardcoded /root/opencode/development
This commit is contained in:
Mauricio López Coria
2026-07-01 23:16:36 -03:00
parent f3d7f3d64f
commit 9aeaeafa3f
14 changed files with 896 additions and 123 deletions
+186 -31
View File
@@ -8,50 +8,90 @@ interface Props {
const { t, whatsappUrl } = Astro.props;
---
<section class="relative overflow-hidden pt-20 pb-28 md:pt-32 md:pb-40">
<div class="absolute inset-0 particle-grid" aria-hidden="true"></div>
<div class="absolute inset-0" style="background: linear-gradient(180deg, transparent 0%, var(--hds-bg) 100%);" aria-hidden="true"></div>
<section
id="hero"
class="relative overflow-hidden flex items-center"
style="min-height: 100dvh; background: var(--hds-bg);"
>
<!-- Atmospheric radial gradient -->
<div
class="absolute inset-0 pointer-events-none"
style="background: var(--hds-gradient-hero);"
aria-hidden="true"
></div>
<div class="absolute top-32 right-8 md:right-16 opacity-50" aria-hidden="true">
<svg width="120" height="120" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="12" height="12" fill="#EE7623" rx="1"/>
<rect x="14" y="0" width="12" height="12" fill="#FA9F5C" rx="1"/>
<rect x="28" y="0" width="12" height="12" fill="#FFCBA1" rx="1"/>
<rect x="0" y="14" width="12" height="12" fill="#FA9F5C" rx="1"/>
<rect x="14" y="14" width="12" height="12" fill="#EE7623" rx="1"/>
<rect x="28" y="14" width="12" height="12" fill="#FA9F5C" rx="1"/>
<rect x="0" y="28" width="12" height="12" fill="#FFCBA1" rx="1"/>
<rect x="14" y="28" width="12" height="12" fill="#FA9F5C" rx="1"/>
<rect x="28" y="28" width="12" height="12" fill="#EE7623" rx="1"/>
</svg>
<!-- Floating decorative shapes (parallax) -->
<div class="absolute inset-0 overflow-hidden pointer-events-none" aria-hidden="true">
<div id="hero-float-top" class="absolute opacity-30" style="top: 15%; right: 12%;">
<svg width="120" height="120" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="12" height="12" fill="#EE7623" rx="1"/>
<rect x="14" y="0" width="12" height="12" fill="#FA9F5C" rx="1"/>
<rect x="28" y="0" width="12" height="12" fill="#FFCBA1" rx="1"/>
<rect x="0" y="14" width="12" height="12" fill="#FA9F5C" rx="1"/>
<rect x="14" y="14" width="12" height="12" fill="#EE7623" rx="1"/>
<rect x="28" y="14" width="12" height="12" fill="#FA9F5C" rx="1"/>
<rect x="0" y="28" width="12" height="12" fill="#FFCBA1" rx="1"/>
<rect x="14" y="28" width="12" height="12" fill="#FA9F5C" rx="1"/>
<rect x="28" y="28" width="12" height="12" fill="#EE7623" rx="1"/>
</svg>
</div>
<div id="hero-float-mid" class="absolute opacity-25" style="top: 55%; left: 8%;">
<svg width="80" height="80" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="10" height="10" fill="#FA9F5C" rx="1"/>
<rect x="12" y="0" width="10" height="10" fill="#EE7623" rx="1"/>
<rect x="0" y="12" width="10" height="10" fill="#FFCBA1" rx="1"/>
<rect x="12" y="12" width="10" height="10" fill="#FA9F5C" rx="1"/>
<rect x="0" y="24" width="10" height="10" fill="#EE7623" rx="1"/>
<rect x="12" y="24" width="10" height="10" fill="#FFCBA1" rx="1"/>
</svg>
</div>
<div id="hero-float-bot" class="absolute opacity-20" style="bottom: 20%; right: 20%;">
<svg width="64" height="64" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="8" height="8" fill="#EE7623" rx="1"/>
<rect x="10" y="0" width="8" height="8" fill="#FFCBA1" rx="1"/>
<rect x="0" y="10" width="8" height="8" fill="#FA9F5C" rx="1"/>
<rect x="10" y="10" width="8" height="8" fill="#EE7623" rx="1"/>
</svg>
</div>
</div>
<div class="absolute bottom-12 left-8 md:left-16 opacity-40" aria-hidden="true">
<svg width="80" height="80" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="10" height="10" fill="#FA9F5C" rx="1"/>
<rect x="12" y="0" width="10" height="10" fill="#EE7623" rx="1"/>
<rect x="0" y="12" width="10" height="10" fill="#FFCBA1" rx="1"/>
<rect x="12" y="12" width="10" height="10" fill="#FA9F5C" rx="1"/>
<rect x="0" y="24" width="10" height="10" fill="#EE7623" rx="1"/>
<rect x="12" y="24" width="10" height="10" fill="#FFCBA1" rx="1"/>
</svg>
</div>
<!-- Decorative glass ring (subtle) -->
<div
id="hero-glass-ring"
class="absolute pointer-events-none rounded-full opacity-0"
style="width: min(600px, 80vw); height: min(600px, 80vw);
top: 50%; left: 70%; transform: translate(-50%, -50%);
border: 1px solid var(--glass-border);
background: var(--glass-bg);
backdrop-filter: blur(40px);
-webkit-backdrop-filter: blur(40px);"
aria-hidden="true"
></div>
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<!-- Content -->
<div class="relative z-10 w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-32 md:py-40">
<div class="max-w-4xl">
<div class="eyebrow mb-7">
<div id="hero-eyebrow" class="eyebrow mb-7 opacity-0">
<span>{t('hero.eyebrow')}</span>
</div>
<h1 class="font-display leading-[0.98] mb-8" style="font-size: clamp(2.75rem, 7vw, 5.5rem); color: var(--hds-fg); letter-spacing: -0.025em; font-weight: 400;">
<h1
id="hero-headline"
class="font-display leading-[0.98] mb-8 opacity-0"
style="font-size: clamp(2.75rem, 7vw, 5.5rem); color: var(--hds-fg); letter-spacing: -0.025em; font-weight: 400;"
>
{t('hero.title')}
</h1>
<p class="text-lg md:text-xl leading-relaxed mb-10 max-w-2xl" style="color: var(--hds-fg-soft);">
<p
id="hero-body"
class="text-lg md:text-xl leading-relaxed mb-10 max-w-2xl opacity-0"
style="color: var(--hds-fg-soft);"
>
{t('hero.body')}
</p>
<div class="flex flex-col sm:flex-row gap-4 mb-14">
<div id="hero-ctas" class="flex flex-col sm:flex-row gap-4 mb-14 opacity-0">
<a href="/planes/" class="btn-primary">
{t('hero.ctaPrimary')}
</a>
@@ -60,7 +100,7 @@ const { t, whatsappUrl } = Astro.props;
</a>
</div>
<div class="flex flex-wrap items-center gap-x-8 gap-y-3 text-sm" style="color: var(--hds-fg-muted);">
<div id="hero-badges" class="flex flex-wrap items-center gap-x-8 gap-y-3 text-sm opacity-0" style="color: var(--hds-fg-muted);">
<span class="flex items-center gap-2">
<span style="color: var(--color-hds-naranja);">●</span>
{t('hero.badge26')}
@@ -80,4 +120,119 @@ const { t, whatsappUrl } = Astro.props;
</div>
</div>
</div>
<!-- Scroll indicator -->
<div id="hero-scroll-indicator" class="absolute bottom-8 left-1/2 -translate-x-1/2 opacity-0 pointer-events-none" aria-hidden="true">
<div class="flex flex-col items-center gap-2" style="color: var(--hds-fg-muted);">
<span class="text-[10px] uppercase tracking-[0.3em] font-semibold">{t('hero.scrollDown')}</span>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 5v14M19 12l-7 7-7-7"/>
</svg>
</div>
</div>
</section>
<script>
import gsap from 'gsap';
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (!prefersReduced) {
const heroTimeline = gsap.timeline({ delay: 0.3 });
heroTimeline
.to('#hero-glass-ring', {
opacity: 1,
scale: 1.05,
duration: 1.4,
ease: 'power3.out',
})
.to('#hero-eyebrow', {
opacity: 1,
y: 0,
duration: 0.6,
ease: 'power2.out',
}, '-=0.8')
.to('#hero-headline', {
opacity: 1,
y: 0,
duration: 0.8,
ease: 'power3.out',
}, '-=0.1')
.to('#hero-body', {
opacity: 1,
y: 0,
duration: 0.7,
ease: 'power2.out',
}, '-=0.2')
.to('#hero-ctas', {
opacity: 1,
y: 0,
duration: 0.6,
ease: 'power2.out',
}, '-=0.3')
.to('#hero-badges', {
opacity: 1,
y: 0,
duration: 0.5,
}, '-=0.4')
.to('#hero-scroll-indicator', {
opacity: 1,
duration: 0.6,
}, '-=0.2');
// Parallax floating shapes
gsap.to('#hero-float-top', {
y: -30,
x: -15,
duration: 3,
ease: 'sine.inOut',
repeat: -1,
yoyo: true,
});
gsap.to('#hero-float-mid', {
y: 25,
x: 12,
duration: 4,
ease: 'sine.inOut',
repeat: -1,
yoyo: true,
delay: 0.5,
});
gsap.to('#hero-float-bot', {
y: -20,
x: -10,
duration: 3.5,
ease: 'sine.inOut',
repeat: -1,
yoyo: true,
delay: 1,
});
} else {
// Show everything without animation
document.querySelectorAll('#hero-eyebrow, #hero-headline, #hero-body, #hero-ctas, #hero-badges, #hero-scroll-indicator, #hero-glass-ring').forEach(el => {
(el as HTMLElement).style.opacity = '1';
});
}
</script>
<style>
#hero-eyebrow {
transform: translateY(16px);
}
#hero-headline {
transform: translateY(24px);
}
#hero-body {
transform: translateY(20px);
}
#hero-ctas {
transform: translateY(16px);
}
#hero-badges {
transform: translateY(12px);
}
#hero-glass-ring {
transform: translate(-50%, -50%) scale(0.85);
}
</style>