feat(v3): rediseño con cloud dividers, animaciones scroll reveal, galería stock, página /servicios con 9 planes, 404 gracioso con robot, planos dark mode con todos los planes

- 9 planes de hosting con tabla completa de Mauri (USD/año)
- /servicios muestra los 3 servicios a medida + 9 planes categorizados
- /planes: 3 destacados + grilla con los 6 restantes
- 404 con robot SVG animado tomando mate (pronet.uy + peugeot style)
- Cloud dividers SVG entre secciones de la home
- Scroll reveal animations (.reveal + .stagger con IntersectionObserver)
- Galería de imágenes stock (datacenters, cables, código) en AVIF + WebP + JPG
- Sección de testimonios con placeholder honesto (Working on it)
- Back-to-top arreglado: ahora usa color naranja + icono blanco, visible en ambos temas
- WorldMap con animación SVG de 4 países
- Toggle light/dark funcional con anti-flash script
- Footer siempre dark con Maldonado, Uruguay
- i18n es/en con toggle y contenido bilingüe

Tech: Astro 5 + Tailwind v4 + Keystatic + Gitea + lftp
This commit is contained in:
Mauri
2026-06-08 23:27:55 -03:00
parent 393f6b0dc3
commit 79fc763025
38 changed files with 1069 additions and 113 deletions
+69
View File
@@ -0,0 +1,69 @@
---
import { monthlyEquivalent, type Plan } from '@/lib/pricing';
interface Props {
plans: Plan[];
whatsappUrl: string;
}
const { plans, whatsappUrl } = Astro.props;
---
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8">
{plans.map((plan) => (
<div
class="relative rounded-2xl p-8 transition-all flex flex-col h-full group hover:-translate-y-1"
style={plan.recommended
? `background: var(--hds-card); border: 2px solid var(--color-hds-naranja); box-shadow: 0 16px 48px rgba(238,118,35,0.18);`
: `background: var(--hds-card); border: 1px solid var(--hds-line);`}
>
{plan.recommended && (
<div class="absolute -top-3.5 left-1/2 -translate-x-1/2 text-[11px] font-bold tracking-[0.2em] uppercase px-4 py-1.5 rounded-full whitespace-nowrap" style="background: var(--color-hds-naranja); color: white; box-shadow: 0 4px 16px rgba(238,118,35,0.4);">
⭐ Recomendado
</div>
)}
<div class="mb-6">
<div class="text-xs font-semibold tracking-[0.25em] uppercase mb-3" style={`color: ${plan.recommended ? 'var(--color-hds-naranja)' : 'var(--hds-fg-muted)'};`}>
{plan.name}
</div>
<div class="flex items-baseline gap-1.5">
<span class="text-2xl font-semibold" style="color: var(--hds-fg);">USD</span>
<span class="font-display leading-none" style="font-size: 4.5rem; color: var(--hds-fg); font-weight: 500; letter-spacing: -0.03em;">{plan.priceUsdYear}</span>
</div>
<div class="text-sm mt-2" style="color: var(--hds-fg-muted);">
por año · ~USD {monthlyEquivalent(plan.priceUsdYear)}/mes
</div>
<div class="text-xs mt-1.5 inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full" style="background: var(--hds-bg-soft); color: var(--hds-fg-muted);">
<span>Técnico: USD {plan.technical}</span>
</div>
</div>
<div class="border-t pt-6 mb-6 flex-grow" style="border-color: var(--hds-line);">
<ul class="space-y-2.5 text-sm" style="color: var(--hds-fg-soft);">
{plan.features.slice(0, 6).map((feature) => (
<li class="flex items-start gap-2.5">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mt-0.5" style="color: var(--color-hds-naranja);" aria-hidden="true">
<polyline points="20 6 9 17 4 12"/>
</svg>
<span>{feature}</span>
</li>
))}
{plan.features.length > 6 && (
<li class="text-xs italic" style="color: var(--hds-fg-muted);">
+ {plan.features.length - 6} características más
</li>
)}
</ul>
</div>
<a
href={`https://wa.me/59899812487?text=${encodeURIComponent(`Hola, me interesa el plan ${plan.name} (USD ${plan.priceUsdYear}/año)`)}`}
target="_blank"
rel="noopener noreferrer"
class={plan.recommended ? 'btn-primary justify-center' : 'btn-secondary justify-center'}
>
Elegir {plan.name}
</a>
</div>
))}
</div>