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
+56
View File
@@ -0,0 +1,56 @@
---
interface Props {
lang: 'es' | 'en';
}
const { lang } = Astro.props;
const items = [
{ src: 'server-room', alt: lang === 'en' ? 'Server room with rack infrastructure' : 'Sala de servidores con racks de infraestructura', title: lang === 'en' ? 'Infrastructure' : 'Infraestructura', col: 'md:col-span-2', row: 'md:row-span-2' },
{ src: 'cables', alt: lang === 'en' ? 'Network cables' : 'Cables de red', title: lang === 'en' ? 'Network' : 'Red', col: '', row: '' },
{ src: 'code', alt: lang === 'en' ? 'Code on screen' : 'Código en pantalla', title: 'Dev', col: '', row: '' },
{ src: 'team', alt: lang === 'en' ? 'Team collaboration' : 'Colaboración del equipo', title: lang === 'en' ? 'Team' : 'Equipo', col: 'md:col-span-2', row: '' },
{ src: 'workspace', alt: lang === 'en' ? 'Workspace' : 'Espacio de trabajo', title: lang === 'en' ? 'Workspace' : 'Workspace', col: '', row: '' },
{ src: 'racks', alt: lang === 'en' ? 'Server racks' : 'Racks de servidores', title: lang === 'en' ? 'Datacenter' : 'Datacenter', col: '', row: '' },
];
---
<section class="py-20 md:py-28" style="background: var(--hds-bg);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-12 reveal">
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold tracking-[0.2em] uppercase" style="background: var(--hds-bg-soft); color: var(--color-hds-naranja);">
{lang === 'en' ? 'Our work' : 'Nuestro trabajo'}
</span>
<h2 class="font-display mt-4" style="font-size: clamp(2rem, 5vw, 3.5rem); color: var(--hds-fg);">
{lang === 'en' ? 'Behind the scenes' : 'Detrás de escena'}.
</h2>
<p class="mt-4 max-w-2xl mx-auto" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'Datacenters, infrastructure, team and the work that powers your projects.'
: 'Datacenters, infraestructura, equipo y el trabajo que sostiene tus proyectos.'}
</p>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 auto-rows-[180px] gap-3 md:gap-4 stagger">
{items.map((item, idx) => (
<figure class={`relative overflow-hidden rounded-xl group ${item.col} ${item.row}`}>
<picture>
<source type="image/avif" srcset={`/images/gallery/${item.src}.avif`} />
<source type="image/webp" srcset={`/images/gallery/${item.src}.webp`} />
<img
src={`/images/gallery/${item.src}.jpg`}
alt={item.alt}
loading="lazy"
decoding="async"
class="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
style={item.row ? '' : 'aspect-ratio: 4/3;'}
/>
</picture>
<figcaption class="absolute inset-x-0 bottom-0 p-4 bg-gradient-to-t from-black/80 to-transparent text-white opacity-0 group-hover:opacity-100 transition-opacity">
<span class="text-xs font-semibold tracking-[0.2em] uppercase" style="color: var(--color-hds-naranja);">
{item.title}
</span>
</figcaption>
</figure>
))}
</div>
</div>
</section>