Files
racing-cards-landing/src/components/CardGallery.astro
Mambo 9646a9684e feat: Racing Cards landing page - Astro + Tailwind v4
- Mobile-first dark mode landing
- Lucide icons (zero emojis)
- Self-hostable (Dockerfile + nginx)
- 10 card images generated with Nano Banana 2
- Sections: Hero, How It Works, Card Gallery, Features, Early Access, Footer
- Simple HTML form (no Netlify dependency)
- Zero JS output, static HTML
2026-03-08 12:43:37 +01:00

72 lines
4.3 KiB
Plaintext

---
interface Card {
name: string;
description: string;
type: 'recta' | 'curva' | 'especial';
image?: string;
}
const cardTypes = {
recta: { label: 'Recta', borderClass: 'border-green-500/30', barClass: 'bg-green-500', textClass: 'text-green-400', bgClass: 'bg-green-500/10' },
curva: { label: 'Curva', borderClass: 'border-yellow-500/30', barClass: 'bg-yellow-500', textClass: 'text-yellow-400', bgClass: 'bg-yellow-500/10' },
especial: { label: 'Especial', borderClass: 'border-primary/30', barClass: 'bg-primary', textClass: 'text-primary', bgClass: 'bg-primary/10' },
};
// Lucide icon SVGs for card type icons
const typeIcons = {
recta: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/></svg>`,
curva: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17m-2 0a2 2 0 1 0 4 0a2 2 0 1 0-4 0"/><path d="M17 7m-2 0a2 2 0 1 0 4 0a2 2 0 1 0-4 0"/><path d="M7 15V9a5 5 0 0 1 10 0"/></svg>`,
especial: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/></svg>`,
};
const cards: Card[] = [
{ name: 'Aleron Movil', description: 'Abre el aleron y vuela. Bonus de velocidad en zonas de recta.', type: 'recta', image: '/images/cards/recta-aleron.png' },
{ name: 'Potencia', description: 'Mas caballos, mas recta. Tu carta base para tramos rapidos.', type: 'recta' },
{ name: 'Rebufo', description: 'Pegate al de delante y aprovecha el aire.', type: 'recta' },
{ name: 'Acelerar', description: 'Salida de curva limpia, pisas a fondo.', type: 'recta' },
{ name: 'Curva Limpia', description: 'La linea perfecta. Ni un metro de mas.', type: 'curva' },
{ name: 'Frenada Tardia', description: 'Frena mas tarde que nadie. Alto riesgo, alta recompensa.', type: 'curva' },
{ name: 'Pit Stop', description: 'Neumaticos nuevos. Pierdes tiempo ahora, lo recuperas despues.', type: 'especial' },
{ name: 'Coche de Seguridad', description: 'Se compacta el peloton. Tu ventaja desaparece... o tu desventaja tambien.', type: 'especial' },
{ name: 'Bandera Roja', description: 'Carrera detenida. Caos para unos, oportunidad para otros.', type: 'especial' },
{ name: 'Lluvia', description: 'Cambia la pista entera. Intermedios o slicks?', type: 'especial' },
];
---
<section class="px-4 py-16 md:py-24 bg-surface/50 border-y border-white/5">
<div class="max-w-6xl mx-auto">
<div class="flex justify-between items-end mb-10">
<h2 class="font-heading text-text text-3xl md:text-4xl font-bold tracking-tight">
Tu baraja,<br />tu estrategia
</h2>
</div>
<!-- Horizontal scroll on mobile -->
<div class="flex gap-4 overflow-x-auto pb-6 snap-x snap-mandatory hide-scrollbar -mx-4 px-4 md:grid md:grid-cols-3 lg:grid-cols-4 md:overflow-visible md:mx-0 md:px-0">
{cards.map((card) => {
const t = cardTypes[card.type];
return (
<div class={`min-w-[200px] md:min-w-0 snap-center shrink-0 md:shrink flex flex-col bg-surface rounded-xl border ${t.borderClass} overflow-hidden shadow-lg hover:-translate-y-1 hover:shadow-xl transition-all duration-200`}>
<div class={`h-1.5 ${t.barClass}`}></div>
{card.image ? (
<div class="h-28 overflow-hidden">
<img src={card.image} alt={card.name} class="w-full h-full object-cover" loading="lazy" />
</div>
) : null}
<div class={`px-3 py-2 ${t.bgClass} flex justify-between items-center`}>
<span class={`text-xs font-bold ${t.textClass} uppercase tracking-wider`}>{t.label}</span>
<span class={t.textClass}>
<Fragment set:html={typeIcons[card.type]} />
</span>
</div>
<div class="p-4 flex flex-col gap-2 flex-1">
<h4 class="text-text font-bold">{card.name}</h4>
<p class="text-xs text-text-muted leading-relaxed flex-1">{card.description}</p>
</div>
</div>
);
})}
</div>
</div>
</section>