Improve frontend traslations 2

This commit is contained in:
Urtzi Alfaro
2025-11-19 07:46:40 +01:00
parent bbf6658759
commit 1f6a679557
14 changed files with 1068 additions and 262 deletions

View File

@@ -0,0 +1,305 @@
# Cost-Effective Pilot Launch Plan for Bakery-IA
## Executive Summary
Total estimated cost: **€50-80/month** (€300-480 for 6-month pilot)
## 1. Server Setup (clouding.io)
**Recommended VPS Configuration:**
- **RAM**: 20 GB
- **CPU**: 8 vCPU
- **Storage**: 200 GB NVMe SSD
- **Cost**: €40-80/month
- **Setup**: Install k3s (lightweight Kubernetes)
**Why clouding.io:**
- Cost-effective European VPS provider
- Good performance/price ratio
- Supports custom ISO and Kubernetes
- Barcelona-based (good latency for Spain)
## 2. Domain & DNS
**Domain Registration:**
- Register domain at **Namecheap** or **Cloudflare Registrar** (~€10-15/year)
- Suggested: `bakeryforecast.es` or `bakery-ia.com`
**DNS Configuration (FREE):**
- Use **Cloudflare DNS** (free tier)
- Benefits: Fast DNS, free SSL proxy option, DDoS protection
- Point A record to your clouding.io VPS IP
## 3. Email Solution (Professional Domain Email)
**RECOMMENDED: Gmail + Google Workspace Trial + Free Forwarding**
### Option A - Gmail SMTP (FREE, best for pilot):
1. Use existing Gmail account with App Password
2. Configure `DEFAULT_FROM_EMAIL: "noreply@bakeryforecast.es"`
3. Set up **email forwarding** at domain registrar:
- `info@bakeryforecast.es` → your personal Gmail
- `noreply@bakeryforecast.es` → your personal Gmail
4. Send via Gmail SMTP, receive via forwarding
5. **Limit**: 500 emails/day (sufficient for 10 tenants)
6. **Cost**: FREE
### Option B - Google Workspace (if you need professional inbox):
- First 14 days FREE trial
- After trial: €5.75/user/month for Business Starter
- Includes: Professional email, 30GB storage, Meet
- Can cancel after pilot if needed
### Option C - Zoho Mail (FREE permanent option):
- FREE tier: 1 domain, 5 users, 5GB/user
- Professional email addresses with your domain
- Send/receive from `info@bakeryforecast.es`
- Web interface + SMTP/IMAP
- **Cost**: FREE forever
### Option D - Cloudflare Email Routing (FREE forwarding only):
- FREE email forwarding from your domain to personal Gmail
- Can receive at `info@bakeryforecast.es` → forwards to Gmail
- Cannot send FROM domain (receive only)
- **Cost**: FREE
**RECOMMENDATION**: Start with **Zoho Mail FREE** for full send/receive capability, or **Gmail SMTP + domain forwarding** if you just need to send notifications.
## 4. WhatsApp Business API (FREE for pilot)
**Setup Meta WhatsApp Business Cloud API:**
1. Create Meta Business Account (FREE)
2. Register WhatsApp Business phone number
- **Use your personal phone number** (must be non-VoIP)
- Can test with personal number initially
- Later: Get dedicated number (~€5-10/month from Twilio or similar)
3. Create app in Meta Developer Portal
4. Configure webhook for delivery status
5. Create message templates and submit for approval (15 min - 24 hours)
**Cost Breakdown:**
- First **1,000 conversations/month**: FREE
- Beyond free tier: €0.01-0.10 per conversation
- For 10 bakeries with ~50 notifications/month each = 500 total = **FREE**
**Personal Phone Testing:**
- You can use your personal WhatsApp number for testing
- Meta allows switching numbers during development
- Later migrate to dedicated business number
## 5. Email Notifications Testing
**Testing Strategy (FREE):**
1. Use **Mailtrap.io** (FREE tier) for development testing
- Catches all emails in fake inbox
- Test templates without sending real emails
- 100 emails/month free
2. Use **Gmail + filters** for real testing
- Create Gmail filter to label test emails
- Send to your own email addresses
3. Use **temp-mail.org** for disposable test addresses
**Production Email Testing:**
- Send test emails to your personal Gmail
- Verify deliverability, template rendering, links
- Check spam score with **mail-tester.com** (FREE)
## 6. SSL Certificates (FREE)
**Let's Encrypt (already configured in your setup):**
- FREE SSL certificates
- Auto-renewal with cert-manager
- Wildcard certificates supported
- **Cost**: FREE
## 7. Additional Cost Optimizations
**What to SKIP in pilot phase:**
- ❌ Managed databases (use containerized PostgreSQL)
- ❌ CDN (not needed for <50 users)
- Premium monitoring tools (use included Prometheus/Grafana)
- Paid backup services (use VPS snapshot feature)
- Multiple replicas (single instance sufficient)
**What to USE (FREE/included):**
- Let's Encrypt SSL
- Cloudflare DNS + DDoS protection
- Gmail SMTP or Zoho Mail
- Meta WhatsApp Business API (1k free conversations)
- Self-hosted monitoring (Prometheus/Grafana)
- VPS snapshots for backups
## 8. Total Cost Breakdown
### Monthly Recurring Costs
| Service | Provider | Monthly Cost |
|---------|----------|-------------|
| VPS Server | clouding.io | 40-80 |
| Domain | Namecheap | 1.25 (€15/year) |
| Email | Zoho/Gmail | 0 (FREE tier) |
| WhatsApp | Meta Business API | 0 (FREE tier) |
| DNS | Cloudflare | 0 (FREE tier) |
| SSL | Let's Encrypt | 0 (FREE) |
| **TOTAL** | | **41-81/month** |
### 6-Month Pilot Total: €246-486
### Optional Add-ons
- Dedicated WhatsApp number: +€5-10/month
- Google Workspace: +€5.75/user/month
- VPS backups: +€8-15/month
- External geocoding API: +€5-10/month
## 9. Implementation Steps
### Week 1: Infrastructure Setup
1. Register domain at Namecheap/Cloudflare
2. Set up clouding.io VPS with Ubuntu 22.04
3. Install k3s (lightweight Kubernetes)
4. Configure Cloudflare DNS pointing to VPS
### Week 2: Email & Communication
1. Set up Zoho Mail FREE account with domain
2. Configure SMTP credentials in Kubernetes secrets
3. Create Meta Business Account for WhatsApp
4. Register your personal phone with WhatsApp Business API
5. Create and submit WhatsApp message templates
### Week 3: Deployment
1. Update Kubernetes secrets with production values
2. Deploy application using Skaffold
3. Configure SSL with Let's Encrypt
4. Test email notifications
5. Test WhatsApp notifications to your personal number
### Week 4: Testing & Launch
1. Send test emails to verify deliverability
2. Send test WhatsApp messages
3. Invite first pilot bakery
4. Monitor costs and usage
## 10. Migration Path (Post-Pilot)
When ready to scale beyond pilot:
- **25-50 tenants**: Upgrade VPS to 32GB RAM (€80-120/month)
- **Email**: Upgrade to paid tier or switch to AWS SES
- **WhatsApp**: Start paying per conversation beyond 1k/month
- **Database**: Consider managed PostgreSQL for HA
- **Monitoring**: Add external monitoring (UptimeRobot, etc.)
## Key Recommendations Summary
1. **VPS**: Use clouding.io (€40-80/month) with k3s
2. **Domain**: Register at Namecheap + use Cloudflare DNS (FREE)
3. **Email**: Zoho Mail FREE tier for professional domain email
4. **WhatsApp**: Meta Business API with personal phone for testing (FREE 1k conversations)
5. **SSL**: Let's Encrypt (FREE, auto-renewal)
6. **Testing**: Use personal email addresses and your WhatsApp number
7. **Skip**: Managed services, CDN, premium monitoring for now
**Total pilot cost: €41-81/month** or **246-486 for 6 months**
---
## Current Infrastructure Status
### What's Already Configured ✅
1. **Email Notifications**: SMTP with Gmail (FREE tier ready)
2. **WhatsApp Notifications**: Meta Business API integration (1,000 FREE conversations/month)
3. **Kubernetes Deployment**: Complete manifests for all services
4. **Docker Compose**: Local development environment
5. **Monitoring**: Prometheus + Grafana configured
6. **Database Migrations**: Alembic for all 18 services
7. **Service Mesh**: RabbitMQ for event-driven architecture
8. **Caching**: Redis configured
9. **SSL/TLS**: cert-manager for automatic certificates
10. **Frontend**: React application with Vite build
### What Needs Setup ❌
1. **Domain Registration**: Buy domain (e.g., bakeryforecast.es)
2. **DNS Configuration**: Point domain to VPS IP
3. **Production Secrets**: Replace placeholder secrets with real values
4. **WhatsApp Business Account**: Register with Meta (1-3 days)
5. **Email SMTP Credentials**: Get Gmail app password or Zoho account
6. **VPS Provisioning**: Set up server at clouding.io
7. **Kubernetes Cluster**: Install k3s on VPS
8. **CI/CD Pipeline**: GitHub Actions for automated deployment (optional)
9. **Backup Strategy**: Configure VPS snapshots
10. **Monitoring Alerts**: Configure Prometheus alerting rules
## Technical Requirements
### VPS Specifications (Minimum for 10 tenants)
- **RAM**: 20 GB
- **CPU**: 8 vCPU
- **Storage**: 200 GB NVMe SSD
- **Network**: 1 Gbps connection
- **OS**: Ubuntu 22.04 LTS
### Storage Breakdown
- **Databases**: 36 GB (18 x 2GB PostgreSQL instances)
- **ML Models**: 10 GB (training/forecasting models)
- **Redis Cache**: 1 GB
- **RabbitMQ**: 2 GB
- **Prometheus Metrics**: 20 GB
- **Container Images**: ~30 GB
- **Growth Buffer**: ~100 GB
- **TOTAL**: 200 GB recommended
### Memory Requirements
- **Application Services**: 14.1 GB requests / 34.5 GB limits
- **Databases**: 4.6 GB requests / 9.2 GB limits
- **Infrastructure (Redis, RabbitMQ)**: 0.8 GB
- **Gateway/Frontend**: 1.8 GB
- **Monitoring**: 1.5 GB
- **TOTAL**: ~20 GB RAM minimum
## Configuration Files to Update
### Email Configuration
**File**: `infrastructure/kubernetes/base/secrets.yaml`
```yaml
SMTP_HOST: "smtp.gmail.com" # or smtp.zoho.com
SMTP_PORT: "587"
SMTP_USERNAME: <base64-encoded-email>
SMTP_PASSWORD: <base64-encoded-app-password>
DEFAULT_FROM_EMAIL: "noreply@bakeryforecast.es"
```
### WhatsApp Configuration
**File**: `infrastructure/kubernetes/base/secrets.yaml`
```yaml
WHATSAPP_ACCESS_TOKEN: <base64-encoded-meta-token>
WHATSAPP_PHONE_NUMBER_ID: <base64-encoded-phone-id>
WHATSAPP_BUSINESS_ACCOUNT_ID: <base64-encoded-account-id>
WHATSAPP_WEBHOOK_VERIFY_TOKEN: <base64-encoded-verify-token>
```
### Domain Configuration
**File**: `infrastructure/kubernetes/base/configmap.yaml`
```yaml
DOMAIN: "bakeryforecast.es"
CORS_ORIGINS: "https://bakeryforecast.es,https://www.bakeryforecast.es"
```
## Useful Links
- **WhatsApp Setup Guide**: `services/notification/WHATSAPP_SETUP_GUIDE.md`
- **Multi-tenant WhatsApp**: `services/notification/MULTI_TENANT_WHATSAPP_IMPLEMENTATION.md`
- **VPS Sizing Guide**: `docs/05-deployment/vps-sizing-production.md`
- **K8s Production Readiness**: `docs/05-deployment/k8s-production-readiness.md`
- **Kubernetes README**: `infrastructure/kubernetes/README.md`
## Next Steps
1. **Register domain** at Namecheap or Cloudflare
2. **Sign up for clouding.io VPS** (20GB RAM, 8 vCPU, 200GB SSD)
3. **Set up Zoho Mail** with your domain (FREE)
4. **Create Meta Business Account** for WhatsApp
5. **Follow Week 1-4 implementation plan** above
---
*Last Updated: 2025-11-19*
*Estimated Total Pilot Cost: €246-486 for 6 months*

View File

@@ -194,7 +194,7 @@ export const SubscriptionPricingCards: React.FC<SubscriptionPricingCardsProps> =
)}
{/* Billing Cycle Toggle */}
<div className="flex justify-center mb-8">
<div className="flex justify-center mb-12">
<div className="inline-flex rounded-lg border-2 border-[var(--border-primary)] p-1 bg-[var(--bg-secondary)]">
<button
onClick={() => setBillingCycle('monthly')}
@@ -241,13 +241,13 @@ export const SubscriptionPricingCards: React.FC<SubscriptionPricingCardsProps> =
key={tier}
{...cardProps}
className={`
group relative rounded-3xl p-8 transition-all duration-300 block
${mode === 'selection' ? 'cursor-pointer' : ''}
group relative rounded-3xl p-8 transition-all duration-300 block no-underline
${mode === 'selection' ? 'cursor-pointer' : mode === 'landing' ? 'cursor-pointer' : ''}
${isSelected
? 'border-2 border-[var(--color-primary)] bg-gradient-to-br from-[var(--color-primary)]/10 via-[var(--color-primary)]/5 to-transparent shadow-2xl ring-4 ring-[var(--color-primary)]/30 scale-[1.02]'
: isPopular
? 'bg-gradient-to-br from-blue-700 via-blue-800 to-blue-900 shadow-2xl transform scale-105 z-10 ring-4 ring-[var(--color-primary)]/20'
: 'bg-[var(--bg-secondary)] border-2 border-[var(--border-primary)] hover:border-[var(--color-primary)]/30 hover:shadow-xl hover:-translate-y-1'
? 'bg-gradient-to-br from-blue-700 via-blue-800 to-blue-900 shadow-2xl transform scale-105 z-10 ring-4 ring-[var(--color-primary)]/20 hover:scale-110 hover:ring-[var(--color-primary)]/40 hover:shadow-3xl'
: 'bg-[var(--bg-secondary)] border-2 border-[var(--border-primary)] hover:border-[var(--color-primary)] hover:shadow-2xl hover:scale-105 hover:ring-4 hover:ring-[var(--color-primary)]/20 hover:-translate-y-2'
}
`}
>

View File

@@ -0,0 +1,94 @@
{
"hero": {
"badge": "Our Mission",
"title_line1": "Technology at the Service",
"title_line2": "of Your Bakery",
"subtitle": "We believe all bakeries deserve the same technological tools as large chains, regardless of their size or business model. We're here to help you compete, grow, and thrive."
},
"mission": {
"title": "Our Mission",
"description": "Help bakeries <strong>reduce waste, increase profitability, and save time</strong> through accessible and easy-to-use artificial intelligence. Whether you produce locally or manage a central workshop with multiple sales points, we want you to focus on your passion: creating exceptional quality products."
},
"vision": {
"title": "Our Vision",
"description": "A world where <strong>no bakery closes due to management problems</strong>, regardless of size or business model. Where technology democratizes access to advanced tools and allows quality and talent to flourish without the administrative burdens that weigh down businesses."
},
"values": {
"title": "Our Values",
"subtitle": "Principles that guide every decision we make",
"sustainability": {
"title": "Sustainability",
"description": "Reducing food waste is not just good for your business, it's our responsibility to the planet. Every bakery that optimizes its production contributes to a more sustainable future."
},
"privacy": {
"title": "Total Privacy",
"description": "Your data is YOUR PROPERTY. 100% servers in Spain, guaranteed GDPR compliance, we never share or sell information. You have total control over your information."
},
"passion": {
"title": "Passion for Baking",
"description": "We love quality bread, whether produced locally or in a central workshop. Our technology exists to help you focus on what you do best: creating exceptional products and serving your customers."
},
"transparency": {
"title": "Transparency",
"description": "We don't promise magic numbers. We tell you the truth: this is a pilot, there will be imperfections, but we'll work with you to build the best tool."
}
},
"founder": {
"title": "The Founder",
"subtitle": "A solo entrepreneur with a clear vision: democratize AI technology for bakeries of all sizes",
"name": "Urtzi Alfaro",
"position": "Founder & CEO",
"intro": "Transformation catalyst, strategic architect, and visionary in advanced technology. With over a decade of international experience leading high-tech and innovation projects, my mission is to create sustainable impact in companies and society on a global scale.",
"bio": "Originally from Donostia-San Sebastián (Basque Country), I worked in London and Cambridge for 7 years, leading global projects with clients in the US, Europe, and China. Now from Madrid, I apply my experience in AI, digital transformation, and product development to help bakeries thrive in the digital age.",
"highlights": {
"experience": {
"title": "International Experience",
"description": "Over a decade leading global high-tech projects, from innovative startups to multinational corporations in the UK, Europe, Asia, and America."
},
"education": {
"title": "Elite Education",
"description": "Telecommunications Engineer (Mondragon University, 2013) with exchange year at École Polytechnique Fédérale de Lausanne (EPFL), Switzerland."
},
"expertise": {
"title": "AI & Innovation Specialization",
"description": "Expert in AI/ML, digital transformation, agile product development, and business model design for large companies and startups."
},
"vision": {
"title": "Global Vision",
"description": "Polyglot (Basque, Spanish, English, French, Chinese) with passion for merging human creativity and cutting-edge technology to create real-value solutions."
}
}
},
"timeline": {
"title": "Our Journey",
"subtitle": "From idea to real impact",
"milestones": {
"inception": {
"year": "2024 Q3",
"title": "Birth of the Idea",
"description": "After seeing family bakeries struggle with waste and tight margins, we decided to apply AI to the problem."
},
"development": {
"year": "2024 Q4",
"title": "Initial Development",
"description": "Built the MVP with feedback from 5 local bakeries. First successful predictions."
},
"pilot": {
"year": "2025 Q1",
"title": "Pilot Launch",
"description": "Looking for 20 pioneering bakeries for the pilot program. 3 months free + lifetime benefits."
},
"expansion": {
"year": "2025 Q2",
"title": "Expansion",
"description": "Public opening after refining the product with pilot feedback. Goal: 100 bakeries."
}
}
},
"cta": {
"title": "Be Part of Our Story",
"subtitle": "We're looking for 20 pioneering bakeries for our pilot program. 3 months free, 20% lifetime discount, and the opportunity to shape the product.",
"primary": "Request Pilot Spot",
"secondary": "See Demo"
}
}

View File

@@ -0,0 +1,65 @@
{
"hero": {
"badge": "Interactive Demo",
"title": "Try El Panadero Digital",
"subtitle": "no commitment",
"description": "Choose the bakery type that fits your business",
"benefits": {
"no_credit_card": "No credit card required",
"access_time": "30 minutes access",
"real_data": "Real data in Spanish"
}
},
"accounts": {
"individual_bakery": {
"title": "Individual Bakery with Local Production",
"subtitle": "Bakery with own production",
"characteristics": {
"title": "Business Characteristics",
"employees": "Employees",
"employees_value": "~8",
"shifts": "Shifts",
"shifts_value": "1/day",
"sales": "Sales",
"sales_value": "Direct",
"products": "Products",
"products_value": "Local"
}
},
"central_baker": {
"title": "Franchise Bakery with Central Kitchen",
"subtitle": "Point of Sale + Central Kitchen",
"characteristics": {
"title": "Business Characteristics",
"employees": "Employees",
"employees_value": "~5-6",
"shifts": "Shifts",
"shifts_value": "2/day",
"model": "Model",
"model_value": "Franchise",
"products": "Products",
"products_value": "From kitchen"
}
},
"features_title": "Included features:",
"demo_badge": "DEMO",
"start_demo": "Start Demo"
},
"loading": {
"initial": "Loading demo accounts...",
"preparing_title": "Preparing your Demo",
"preparing_description": "Setting up your personalized environment with sample data...",
"ready_title": "Ready! Redirecting...",
"ready_description": "Your environment is ready. Accessing dashboard...",
"estimated_time": "Estimated time: ~{seconds}s",
"tip": "💡 Tip: The demo includes real data from Spanish bakeries so you can explore all features"
},
"footer": {
"have_account": "Already have an account?",
"login_link": "Login here"
},
"errors": {
"loading_accounts": "Error loading demo accounts",
"creating_session": "Error creating demo session"
}
}

View File

@@ -0,0 +1,94 @@
{
"hero": {
"badge": "Nuestra Misión",
"title_line1": "Tecnología al Servicio",
"title_line2": "de Tu Panadería",
"subtitle": "Creemos que todas las panaderías merecen las mismas herramientas tecnológicas que las grandes cadenas, sin importar su tamaño o modelo de negocio. Estamos aquí para ayudarte a competir, crecer y prosperar."
},
"mission": {
"title": "Nuestra Misión",
"description": "Ayudar a panaderías a <strong>reducir desperdicios, aumentar rentabilidad y ahorrar tiempo</strong> mediante inteligencia artificial accesible y fácil de usar. Ya sea que produzcas localmente o gestiones un obrador central con múltiples puntos de venta, queremos que puedas enfocarte en tu pasión: crear productos de calidad excepcional."
},
"vision": {
"title": "Nuestra Visión",
"description": "Un mundo donde <strong>ninguna panadería cierre por problemas de gestión</strong>, sin importar su tamaño o modelo de negocio. Donde la tecnología democratiza el acceso a herramientas avanzadas y permite que la calidad y el talento florezcan sin las cargas administrativas que agobian a los negocios."
},
"values": {
"title": "Nuestros Valores",
"subtitle": "Principios que guían cada decisión que tomamos",
"sustainability": {
"title": "Sostenibilidad",
"description": "Reducir el desperdicio alimentario no es solo bueno para tu negocio, es nuestra responsabilidad con el planeta. Cada panadería que optimiza su producción contribuye a un futuro más sostenible."
},
"privacy": {
"title": "Privacidad Total",
"description": "Tus datos son TU PROPIEDAD. Servidores 100% en España, cumplimiento RGPD garantizado, nunca compartimos ni vendemos información. Tienes control total sobre tu información."
},
"passion": {
"title": "Pasión por la Panadería",
"description": "Amamos el pan de calidad, sea producido localmente o en un obrador central. Nuestra tecnología existe para ayudarte a enfocarte en lo que mejor sabes hacer: crear productos excepcionales y servir a tus clientes."
},
"transparency": {
"title": "Transparencia",
"description": "No prometemos números mágicos. Te contamos la verdad: esto es un piloto, habrá imperfecciones, pero trabajaremos contigo para construir la mejor herramienta."
}
},
"founder": {
"title": "El Fundador",
"subtitle": "Un emprendedor en solitario con una visión clara: democratizar la tecnología de IA para panaderías de todos los tamaños",
"name": "Urtzi Alfaro",
"position": "Fundador & CEO",
"intro": "Catalizador de transformación, arquitecto estratégico y visionario en tecnología avanzada. Con más de una década de experiencia internacional liderando proyectos de alta tecnología e innovación, mi misión es crear impacto sostenible en empresas y sociedad a escala global.",
"bio": "Natural de Donostia-San Sebastián (País Vasco), he trabajado en Londres y Cambridge durante 7 años, liderando proyectos globales con clientes en EE.UU., Europa y China. Ahora desde Madrid, aplico mi experiencia en IA, transformación digital y desarrollo de productos para ayudar a las panaderías a prosperar en la era digital.",
"highlights": {
"experience": {
"title": "Experiencia Internacional",
"description": "Más de una década liderando proyectos globales de alta tecnología, desde startups innovadoras hasta corporaciones multinacionales en Reino Unido, Europa, Asia y América."
},
"education": {
"title": "Formación de Élite",
"description": "Ingeniero en Telecomunicaciones (Mondragon University, 2013) con año de intercambio en École Polytechnique Fédérale de Lausanne (EPFL), Suiza."
},
"expertise": {
"title": "Especialización en IA & Innovación",
"description": "Experto en IA/ML, transformación digital, desarrollo de productos ágiles y diseño de modelos de negocio para grandes empresas y startups."
},
"vision": {
"title": "Visión Global",
"description": "Políglota (euskera, español, inglés, francés, chino) con pasión por fusionar creatividad humana y tecnología de vanguardia para crear soluciones de valor real."
}
}
},
"timeline": {
"title": "Nuestro Camino",
"subtitle": "De la idea al impacto real",
"milestones": {
"inception": {
"year": "2024 Q3",
"title": "Nacimiento de la Idea",
"description": "Después de ver panaderías familiares luchar con desperdicios y márgenes estrechos, decidimos aplicar IA al problema."
},
"development": {
"year": "2024 Q4",
"title": "Desarrollo Inicial",
"description": "Construimos el MVP con feedback de 5 panaderías locales. Primeras predicciones exitosas."
},
"pilot": {
"year": "2025 Q1",
"title": "Lanzamiento Piloto",
"description": "Buscamos 20 panaderías pioneras para el programa piloto. 3 meses gratis + beneficios de por vida."
},
"expansion": {
"year": "2025 Q2",
"title": "Expansión",
"description": "Apertura pública tras refinar el producto con feedback del piloto. Objetivo: 100 panaderías."
}
}
},
"cta": {
"title": "Sé Parte de Nuestra Historia",
"subtitle": "Estamos buscando 20 panaderías pioneras para nuestro programa piloto. 3 meses gratis, 20% descuento de por vida, y la oportunidad de moldear el producto.",
"primary": "Solicitar Plaza en el Piloto",
"secondary": "Ver Demo"
}
}

View File

@@ -0,0 +1,65 @@
{
"hero": {
"badge": "Demo Interactiva",
"title": "Prueba El Panadero Digital",
"subtitle": "sin compromiso",
"description": "Elige el tipo de panadería que se ajuste a tu negocio",
"benefits": {
"no_credit_card": "Sin tarjeta de crédito",
"access_time": "30 minutos de acceso",
"real_data": "Datos reales en español"
}
},
"accounts": {
"individual_bakery": {
"title": "Panadería Individual con Producción local",
"subtitle": "Panadería con producción propia",
"characteristics": {
"title": "Características del negocio",
"employees": "Empleados",
"employees_value": "~8",
"shifts": "Turnos",
"shifts_value": "1/día",
"sales": "Ventas",
"sales_value": "Directas",
"products": "Productos",
"products_value": "Local"
}
},
"central_baker": {
"title": "Panadería Franquiciada con Obrador Central",
"subtitle": "Punto de Venta + Obrador Central",
"characteristics": {
"title": "Características del negocio",
"employees": "Empleados",
"employees_value": "~5-6",
"shifts": "Turnos",
"shifts_value": "2/día",
"model": "Modelo",
"model_value": "Franquicia",
"products": "Productos",
"products_value": "De obrador"
}
},
"features_title": "Funcionalidades incluidas:",
"demo_badge": "DEMO",
"start_demo": "Iniciar Demo"
},
"loading": {
"initial": "Cargando cuentas demo...",
"preparing_title": "Preparando tu Demo",
"preparing_description": "Configurando tu entorno personalizado con datos de muestra...",
"ready_title": "¡Listo! Redirigiendo...",
"ready_description": "Tu entorno está listo. Accediendo al dashboard...",
"estimated_time": "Tiempo estimado: ~{seconds}s",
"tip": "💡 Tip: La demo incluye datos reales de panaderías españolas para que puedas explorar todas las funcionalidades"
},
"footer": {
"have_account": "¿Ya tienes una cuenta?",
"login_link": "Inicia sesión aquí"
},
"errors": {
"loading_accounts": "Error al cargar las cuentas demo",
"creating_session": "Error al crear sesión demo"
}
}

View File

@@ -0,0 +1,94 @@
{
"hero": {
"badge": "Gure Eginkizuna",
"title_line1": "Teknologia Zure Okindegiaren",
"title_line2": "Zerbitzura",
"subtitle": "Sinesmen sendoa dugu okindegi guztiek kate handien tresna teknologiko berdinak merezi dituztela, haien tamaina edo negozio-eredua edozein dela ere. Hemen gaude zu laguntzeko lehiatzeko, hazteko eta lortzeko."
},
"mission": {
"title": "Gure Eginkizuna",
"description": "Okindegeiei lagundu <strong>hondakinak murrizten, errentagarritasuna handitzen eta denbora aurrezten</strong> adimen artifizial irisgarri eta erabilterraza erabiliz. Lokalean ekoizten duzun edo zenbait salmenta-punturekin lantegi zentral bat kudeatzen duzun, nahi dugu zure pasioan zentratu zaitezen: kalitate bereziko produktuak sortzea."
},
"vision": {
"title": "Gure Ikuspegia",
"description": "Mundu bat non <strong>okindegi batek ere ez duen itxi behar kudeaketa-arazoengatik</strong>, tamaina edo negozio-eredua edozein dela ere. Non teknologiak tresna aurreratuen sarbidea demokratizatzen duen eta kalitatea eta talentua loratzea ahalbidetzen duen negozioak zapaltzen dituzten administrazio-zama gabe."
},
"values": {
"title": "Gure Balioak",
"subtitle": "Hartzen dugun erabaki bakoitza gidatzen duten printzipioak",
"sustainability": {
"title": "Iraunkortasuna",
"description": "Elikagaien hondakina murriztea ez da zure negoziorako onuragarria bakarrik, planetarekiko gure erantzukizuna da. Ekoizpena optimizatzen duen okindegi bakoitzak etorkizun iraunkorrago baterako laguntzen du."
},
"privacy": {
"title": "Pribatutasun Osoa",
"description": "Zure datuak ZURE JABETZAKOAK dira. Zerbitzariak %100 Espainian, GDBRaren betetze bermea, inoiz ez dugu informazioa partekatzen edo saltzen. Zure informazioaren gaineko kontrol osoa duzu."
},
"passion": {
"title": "Okinaritzarako Pasioa",
"description": "Kalitate ogiaren maite dugu, lokalean nahiz lantegi zentralean ekoiztua. Gure teknologia existitzen da hoberen egiten duzunean zentratzeko laguntza emateko: produktu bikainak sortzea eta zure bezeroei zerbitzua ematea."
},
"transparency": {
"title": "Gardentasuna",
"description": "Ez ditugu zenbaki magikoak agintzen. Egia esaten dizugu: pilotu bat da hau, ezinbesteko akatsen bat egongo da, baina zurekin lan egingo dugu tresna onena eraikitzeko."
}
},
"founder": {
"title": "Sortzailea",
"subtitle": "Enpresaburu bakartia ikusmen argi batekin: AI teknologia demokratizatu tamaina guztietako okindegetarako",
"name": "Urtzi Alfaro",
"position": "Sortzailea & Zuzendari Nagusia",
"intro": "Eraldaketaren katalizatzailea, arkitekto estrategikoa eta aurreratutako teknologiako ikuslaria. Nazioarteko esperientzia hamarkada bat baino gehiagorekin teknologia altuko eta berrikuntzako proiektuak gidatzen, nire eginkizuna enpresa eta gizartean iraunkortasun inpaktua sortzea da eskala globalean.",
"bio": "Donostia-San Sebastiangoa (Euskal Herria), Londresen eta Cambridgen 7 urtez lan egin dut, AEBetan, Europan eta Txinan bezeroak dituzten proiektu globalak gidatzen. Orain Madrildik, nire esperientzia AI-n, eraldaketa digitalean eta produktuen garapenean aplikatzen dut okindegiek era digitalean lortzeko laguntza emateko.",
"highlights": {
"experience": {
"title": "Nazioarteko Esperientzia",
"description": "Hamarkada bat baino gehiago teknologia altuko proiektu globalak gidatzen, startup berritzaileetatik korporazio multinazionaletara Erresuma Batuan, Europan, Asian eta Amerikan."
},
"education": {
"title": "Elite Prestakuntza",
"description": "Telekomunikazioko Ingeniaritza (Mondragon Unibertsitatea, 2013) École Polytechnique Fédérale de Lausanne (EPFL), Suitza-n truke-urte batekin."
},
"expertise": {
"title": "AI eta Berrikuntzaren Espezializazioa",
"description": "Adituak AI/ML-n, eraldaketa digitalean, produktu garapenean agilean eta negozio-ereduen diseinuan enpresa handiak eta startups-etarako."
},
"vision": {
"title": "Ikusmen Globala",
"description": "Poliglota (euskara, gaztelania, ingelesa, frantsesa, txinera) giza sormena eta teknologia aurreratua fusionatzeko pasioaz, balio errealeko konponbideak sortzeko."
}
}
},
"timeline": {
"title": "Gure Bidea",
"subtitle": "Ideiatik inpaktu errealera",
"milestones": {
"inception": {
"year": "2024 H3",
"title": "Idearen Jaiotza",
"description": "Familia okindegiak hondakinekin eta marjina estuetan borrokatzen ikusi ondoren, AI aplikatu genuen arazoari."
},
"development": {
"year": "2024 H4",
"title": "Hasierako Garapena",
"description": "MVP eraikitzen 5 okindegi lokalekin feedback-arekin. Lehen aurreikuspen arrakastatsuak."
},
"pilot": {
"year": "2025 H1",
"title": "Pilotu Abiaraztea",
"description": "20 okindegi aitzindari bilatzen pilotu-programarako. 3 hilabete doan + bizitza osoko onurak."
},
"expansion": {
"year": "2025 H2",
"title": "Hedapena",
"description": "Ireki publikoa pilotuko feedback-arekin produktua finkatu ondoren. Helburua: 100 okindegi."
}
}
},
"cta": {
"title": "Izan Gure Historiaren Parte",
"subtitle": "20 okindegi aitzindari bilatzen ari gara gure pilotu-programarako. 3 hilabete doan, %20ko deskontua bizitza osoan, eta produktua moldatzeko aukera.",
"primary": "Eskatu Pilotuko Plaza",
"secondary": "Ikusi Demoa"
}
}

View File

@@ -0,0 +1,65 @@
{
"hero": {
"badge": "Demo Interaktiboa",
"title": "Probatu El Panadero Digital",
"subtitle": "konpromisorik gabe",
"description": "Aukeratu zure negozioari egokitzen zaion okindegi mota",
"benefits": {
"no_credit_card": "Kreditu txartelik gabe",
"access_time": "30 minutuko sarbidea",
"real_data": "Datu errealak espainieraz"
}
},
"accounts": {
"individual_bakery": {
"title": "Banakako Okindegi Tokiko Ekoizpenarekin",
"subtitle": "Bere ekoizpena duen okindegi",
"characteristics": {
"title": "Negozio Ezaugarriak",
"employees": "Langileak",
"employees_value": "~8",
"shifts": "Txandak",
"shifts_value": "1/eguna",
"sales": "Salmentak",
"sales_value": "Zuzenak",
"products": "Produktuak",
"products_value": "Tokikoak"
}
},
"central_baker": {
"title": "Frantzizia Okindegi Sukalde Zentralarekin",
"subtitle": "Salmenta Puntua + Sukalde Zentrala",
"characteristics": {
"title": "Negozio Ezaugarriak",
"employees": "Langileak",
"employees_value": "~5-6",
"shifts": "Txandak",
"shifts_value": "2/eguna",
"model": "Modeloa",
"model_value": "Frantzizia",
"products": "Produktuak",
"products_value": "Sukaldetik"
}
},
"features_title": "Barne hartutako funtzionalitateak:",
"demo_badge": "DEMO",
"start_demo": "Demoa Hasi"
},
"loading": {
"initial": "Demo kontuak kargatzen...",
"preparing_title": "Zure Demoa Prestatzen",
"preparing_description": "Zure ingurune pertsonalizatua konfiguratzen lagindako datuekin...",
"ready_title": "Prest! Birbideratzen...",
"ready_description": "Zure ingurunea prest dago. Panelera sartzen...",
"estimated_time": "Aurreikusitako denbora: ~{seconds}s",
"tip": "💡 Aholkua: Demoak espainiar okindegi errealeko datuak ditu funtzionalitate guztiak arakatzeko"
},
"footer": {
"have_account": "Kontu bat duzu dagoeneko?",
"login_link": "Saioa hasi hemen"
},
"errors": {
"loading_accounts": "Errorea demo kontuak kargatzean",
"creating_session": "Errorea demo saioa sortzean"
}
}

View File

@@ -1,4 +1,12 @@
{
"toc": {
"automatic": "Sistema Automatikoa",
"local": "Adimen Lokala",
"forecasting": "Eskariaren Aurreikuspena",
"waste": "Hondakinen Murrizketa",
"sustainability": "Iraunkortasuna",
"business": "Negozio Ereduak"
},
"hero": {
"title": "Bakery-IA Nola Lan Egiten Duen Zuretzat Egunero",
"subtitle": "Funtzionalitate guztiak hizkuntza sinplean azalduta okindegiaren jabearentzat"

View File

@@ -18,6 +18,9 @@ import wizardsEs from './es/wizards.json';
import subscriptionEs from './es/subscription.json';
import purchaseOrdersEs from './es/purchase_orders.json';
import helpEs from './es/help.json';
import featuresEs from './es/features.json';
import aboutEs from './es/about.json';
import demoEs from './es/demo.json';
// English translations
import commonEn from './en/common.json';
@@ -39,6 +42,9 @@ import wizardsEn from './en/wizards.json';
import subscriptionEn from './en/subscription.json';
import purchaseOrdersEn from './en/purchase_orders.json';
import helpEn from './en/help.json';
import featuresEn from './en/features.json';
import aboutEn from './en/about.json';
import demoEn from './en/demo.json';
// Basque translations
import commonEu from './eu/common.json';
@@ -60,6 +66,9 @@ import wizardsEu from './eu/wizards.json';
import subscriptionEu from './eu/subscription.json';
import purchaseOrdersEu from './eu/purchase_orders.json';
import helpEu from './eu/help.json';
import featuresEu from './eu/features.json';
import aboutEu from './eu/about.json';
import demoEu from './eu/demo.json';
// Translation resources by language
export const resources = {
@@ -83,6 +92,9 @@ export const resources = {
subscription: subscriptionEs,
purchase_orders: purchaseOrdersEs,
help: helpEs,
features: featuresEs,
about: aboutEs,
demo: demoEs,
},
en: {
common: commonEn,
@@ -104,6 +116,9 @@ export const resources = {
subscription: subscriptionEn,
purchase_orders: purchaseOrdersEn,
help: helpEn,
features: featuresEn,
about: aboutEn,
demo: demoEn,
},
eu: {
common: commonEu,
@@ -125,6 +140,9 @@ export const resources = {
subscription: subscriptionEu,
purchase_orders: purchaseOrdersEu,
help: helpEu,
features: featuresEu,
about: aboutEu,
demo: demoEu,
},
};
@@ -161,7 +179,7 @@ export const languageConfig = {
};
// Namespaces available in translations
export const namespaces = ['common', 'auth', 'inventory', 'foodSafety', 'suppliers', 'orders', 'recipes', 'errors', 'dashboard', 'production', 'equipment', 'landing', 'settings', 'ajustes', 'reasoning', 'wizards', 'subscription', 'purchase_orders', 'help'] as const;
export const namespaces = ['common', 'auth', 'inventory', 'foodSafety', 'suppliers', 'orders', 'recipes', 'errors', 'dashboard', 'production', 'equipment', 'landing', 'settings', 'ajustes', 'reasoning', 'wizards', 'subscription', 'purchase_orders', 'help', 'features', 'about', 'demo'] as const;
export type Namespace = typeof namespaces[number];
// Helper function to get language display name
@@ -175,7 +193,7 @@ export const isSupportedLanguage = (language: string): language is SupportedLang
};
// Export individual language modules for direct imports
export { commonEs, authEs, inventoryEs, foodSafetyEs, suppliersEs, ordersEs, recipesEs, errorsEs, equipmentEs, landingEs, settingsEs, ajustesEs, reasoningEs, wizardsEs, wizardsEn, wizardsEu, helpEs, helpEn, helpEu };
export { commonEs, authEs, inventoryEs, foodSafetyEs, suppliersEs, ordersEs, recipesEs, errorsEs, equipmentEs, landingEs, settingsEs, ajustesEs, reasoningEs, wizardsEs, wizardsEn, wizardsEu, helpEs, helpEn, helpEu, featuresEs, featuresEn, featuresEu, aboutEs, aboutEn, aboutEu, demoEs, demoEn, demoEu };
// Default export with all translations
export default resources;

View File

@@ -17,74 +17,74 @@ import {
} from 'lucide-react';
const AboutPage: React.FC = () => {
const { t } = useTranslation();
const { t } = useTranslation('about');
const values = [
{
icon: Leaf,
title: 'Sostenibilidad',
description: 'Reducir el desperdicio alimentario no es solo bueno para tu negocio, es nuestra responsabilidad con el planeta. Cada panadería que optimiza su producción contribuye a un futuro más sostenible.',
title: t('values.sustainability.title'),
description: t('values.sustainability.description'),
},
{
icon: Shield,
title: 'Privacidad Total',
description: 'Tus datos son TU PROPIEDAD. Servidores 100% en España, cumplimiento RGPD garantizado, nunca compartimos ni vendemos información. Tienes control total sobre tu información.',
title: t('values.privacy.title'),
description: t('values.privacy.description'),
},
{
icon: Heart,
title: 'Pasión por la Panadería',
description: 'Amamos el pan de calidad, sea producido localmente o en un obrador central. Nuestra tecnología existe para ayudarte a enfocarte en lo que mejor sabes hacer: crear productos excepcionales y servir a tus clientes.',
title: t('values.passion.title'),
description: t('values.passion.description'),
},
{
icon: Users,
title: 'Transparencia',
description: 'No prometemos números mágicos. Te contamos la verdad: esto es un piloto, habrá imperfecciones, pero trabajaremos contigo para construir la mejor herramienta.',
title: t('values.transparency.title'),
description: t('values.transparency.description'),
},
];
const founderHighlights = [
{
icon: Brain,
title: 'Experiencia Internacional',
description: 'Más de una década liderando proyectos globales de alta tecnología, desde startups innovadoras hasta corporaciones multinacionales en Reino Unido, Europa, Asia y América.',
title: t('founder.highlights.experience.title'),
description: t('founder.highlights.experience.description'),
},
{
icon: Award,
title: 'Formación de Élite',
description: 'Ingeniero en Telecomunicaciones (Mondragon University, 2013) con año de intercambio en École Polytechnique Fédérale de Lausanne (EPFL), Suiza.',
title: t('founder.highlights.education.title'),
description: t('founder.highlights.education.description'),
},
{
icon: TrendingUp,
title: 'Especialización en IA & Innovación',
description: 'Experto en IA/ML, transformación digital, desarrollo de productos ágiles y diseño de modelos de negocio para grandes empresas y startups.',
title: t('founder.highlights.expertise.title'),
description: t('founder.highlights.expertise.description'),
},
{
icon: Users,
title: 'Visión Global',
description: 'Políglota (euskera, español, inglés, francés, chino) con pasión por fusionar creatividad humana y tecnología de vanguardia para crear soluciones de valor real.',
title: t('founder.highlights.vision.title'),
description: t('founder.highlights.vision.description'),
},
];
const milestones = [
{
year: '2024 Q3',
title: 'Nacimiento de la Idea',
description: 'Después de ver panaderías familiares luchar con desperdicios y márgenes estrechos, decidimos aplicar IA al problema.',
year: t('timeline.milestones.inception.year'),
title: t('timeline.milestones.inception.title'),
description: t('timeline.milestones.inception.description'),
},
{
year: '2024 Q4',
title: 'Desarrollo Inicial',
description: 'Construimos el MVP con feedback de 5 panaderías locales. Primeras predicciones exitosas.',
year: t('timeline.milestones.development.year'),
title: t('timeline.milestones.development.title'),
description: t('timeline.milestones.development.description'),
},
{
year: '2025 Q1',
title: 'Lanzamiento Piloto',
description: 'Buscamos 20 panaderías pioneras para el programa piloto. 3 meses gratis + beneficios de por vida.',
year: t('timeline.milestones.pilot.year'),
title: t('timeline.milestones.pilot.title'),
description: t('timeline.milestones.pilot.description'),
},
{
year: '2025 Q2',
title: 'Expansión',
description: 'Apertura pública tras refinar el producto con feedback del piloto. Objetivo: 100 panaderías.',
year: t('timeline.milestones.expansion.year'),
title: t('timeline.milestones.expansion.title'),
description: t('timeline.milestones.expansion.description'),
},
];
@@ -105,15 +105,14 @@ const AboutPage: React.FC = () => {
<div className="text-center max-w-4xl mx-auto">
<div className="inline-flex items-center gap-2 bg-[var(--color-primary)]/10 text-[var(--color-primary)] px-4 py-2 rounded-full text-sm font-medium mb-6">
<Sparkles className="w-4 h-4" />
<span>Nuestra Misión</span>
<span>{t('hero.badge')}</span>
</div>
<h1 className="text-4xl lg:text-6xl font-extrabold text-[var(--text-primary)] mb-6">
Tecnología al Servicio
<span className="block text-[var(--color-primary)]">de Tu Panadería</span>
{t('hero.title_line1')}
<span className="block text-[var(--color-primary)]">{t('hero.title_line2')}</span>
</h1>
<p className="text-xl text-[var(--text-secondary)] leading-relaxed">
Creemos que todas las panaderías merecen las mismas herramientas tecnológicas que las grandes cadenas,
sin importar su tamaño o modelo de negocio. Estamos aquí para ayudarte a competir, crecer y prosperar.
{t('hero.subtitle')}
</p>
</div>
</div>
@@ -128,12 +127,8 @@ const AboutPage: React.FC = () => {
<div className="w-16 h-16 bg-blue-600 rounded-2xl flex items-center justify-center mb-6">
<Target className="w-8 h-8 text-white" />
</div>
<h2 className="text-3xl font-bold text-[var(--text-primary)] mb-4">Nuestra Misión</h2>
<p className="text-lg text-[var(--text-secondary)] leading-relaxed">
Ayudar a panaderías a <strong>reducir desperdicios, aumentar rentabilidad y ahorrar tiempo</strong>
mediante inteligencia artificial accesible y fácil de usar. Ya sea que produzcas localmente o gestiones un obrador central
con múltiples puntos de venta, queremos que puedas enfocarte en tu pasión: crear productos de calidad excepcional.
</p>
<h2 className="text-3xl font-bold text-[var(--text-primary)] mb-4">{t('mission.title')}</h2>
<p className="text-lg text-[var(--text-secondary)] leading-relaxed" dangerouslySetInnerHTML={{ __html: t('mission.description') }} />
</div>
{/* Vision */}
@@ -141,12 +136,8 @@ const AboutPage: React.FC = () => {
<div className="w-16 h-16 bg-amber-600 rounded-2xl flex items-center justify-center mb-6">
<Brain className="w-8 h-8 text-white" />
</div>
<h2 className="text-3xl font-bold text-[var(--text-primary)] mb-4">Nuestra Visión</h2>
<p className="text-lg text-[var(--text-secondary)] leading-relaxed">
Un mundo donde <strong>ninguna panadería cierre por problemas de gestión</strong>, sin importar su tamaño o modelo de negocio.
Donde la tecnología democratiza el acceso a herramientas avanzadas y permite que la calidad y el talento florezcan
sin las cargas administrativas que agobian a los negocios.
</p>
<h2 className="text-3xl font-bold text-[var(--text-primary)] mb-4">{t('vision.title')}</h2>
<p className="text-lg text-[var(--text-secondary)] leading-relaxed" dangerouslySetInnerHTML={{ __html: t('vision.description') }} />
</div>
</div>
</div>
@@ -157,10 +148,10 @@ const AboutPage: React.FC = () => {
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-16">
<h2 className="text-3xl lg:text-4xl font-extrabold text-[var(--text-primary)] mb-4">
Nuestros Valores
{t('values.title')}
</h2>
<p className="text-xl text-[var(--text-secondary)] max-w-3xl mx-auto">
Principios que guían cada decisión que tomamos
{t('values.subtitle')}
</p>
</div>
@@ -186,10 +177,10 @@ const AboutPage: React.FC = () => {
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-16">
<h2 className="text-3xl lg:text-4xl font-extrabold text-[var(--text-primary)] mb-4">
El Fundador
{t('founder.title')}
</h2>
<p className="text-xl text-[var(--text-secondary)] max-w-3xl mx-auto">
Un emprendedor en solitario con una visión clara: democratizar la tecnología de IA para panaderías de todos los tamaños
{t('founder.subtitle')}
</p>
</div>
@@ -201,18 +192,13 @@ const AboutPage: React.FC = () => {
UA
</div>
<div className="flex-1 text-center md:text-left">
<h3 className="text-3xl font-bold text-[var(--text-primary)] mb-2">Urtzi Alfaro</h3>
<p className="text-xl text-[var(--color-primary)] font-medium mb-4">Fundador & CEO</p>
<h3 className="text-3xl font-bold text-[var(--text-primary)] mb-2">{t('founder.name')}</h3>
<p className="text-xl text-[var(--color-primary)] font-medium mb-4">{t('founder.position')}</p>
<p className="text-[var(--text-secondary)] leading-relaxed mb-4">
Catalizador de transformación, arquitecto estratégico y visionario en tecnología avanzada.
Con más de una década de experiencia internacional liderando proyectos de alta tecnología e innovación,
mi misión es crear impacto sostenible en empresas y sociedad a escala global.
{t('founder.intro')}
</p>
<p className="text-[var(--text-secondary)] leading-relaxed">
Natural de Donostia-San Sebastián (País Vasco), he trabajado en Londres y Cambridge durante 7 años,
liderando proyectos globales con clientes en EE.UU., Europa y China. Ahora desde Madrid,
aplico mi experiencia en IA, transformación digital y desarrollo de productos para ayudar
a las panaderías a prosperar en la era digital.
{t('founder.bio')}
</p>
</div>
</div>
@@ -242,10 +228,10 @@ const AboutPage: React.FC = () => {
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-16">
<h2 className="text-3xl lg:text-4xl font-extrabold text-[var(--text-primary)] mb-4">
Nuestro Camino
{t('timeline.title')}
</h2>
<p className="text-xl text-[var(--text-secondary)]">
De la idea al impacto real
{t('timeline.subtitle')}
</p>
</div>
@@ -276,25 +262,24 @@ const AboutPage: React.FC = () => {
<section className="py-20 bg-gradient-to-r from-[var(--color-primary)] to-orange-600">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 className="text-3xl lg:text-4xl font-bold text-white mb-6">
Parte de Nuestra Historia
{t('cta.title')}
</h2>
<p className="text-xl text-white/90 mb-8 leading-relaxed">
Estamos buscando 20 panaderías pioneras para nuestro programa piloto.
3 meses gratis, 20% descuento de por vida, y la oportunidad de moldear el producto.
{t('cta.subtitle')}
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link
to="/register"
className="inline-flex items-center justify-center gap-2 px-8 py-4 bg-white text-[var(--color-primary)] rounded-xl font-bold hover:shadow-2xl transition-all hover:scale-105"
>
<span>Solicitar Plaza en el Piloto</span>
<span>{t('cta.primary')}</span>
<ArrowRight className="w-5 h-5" />
</Link>
<Link
to="/demo"
className="inline-flex items-center justify-center gap-2 px-8 py-4 border-2 border-white text-white rounded-xl font-bold hover:bg-white hover:text-[var(--color-primary)] transition-all"
>
<span>Ver Demo</span>
<span>{t('cta.secondary')}</span>
</Link>
</div>
</div>

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect, useCallback } from 'react';
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { PublicLayout } from '../../components/layout';
import { Button } from '../../components/ui';
import { getDemoAccounts, createDemoSession, DemoAccount, demoSessionAPI } from '../../api/services/demo';
@@ -10,6 +11,7 @@ import { markTourAsStartPending } from '../../features/demo-onboarding';
const POLL_INTERVAL_MS = 1500; // Poll every 1.5 seconds
export const DemoPage: React.FC = () => {
const { t } = useTranslation();
const [demoAccounts, setDemoAccounts] = useState<DemoAccount[]>([]);
const [loading, setLoading] = useState(true);
const [creatingSession, setCreatingSession] = useState(false);
@@ -23,7 +25,7 @@ export const DemoPage: React.FC = () => {
const accounts = await getDemoAccounts();
setDemoAccounts(accounts);
} catch (err) {
setError('Error al cargar las cuentas demo');
setError(t('demo:errors.loading_accounts', 'Error al cargar las cuentas demo'));
console.error('Error fetching demo accounts:', err);
} finally {
setLoading(false);
@@ -152,7 +154,7 @@ export const DemoPage: React.FC = () => {
clearInterval(pollInterval);
}
} catch (err: any) {
setError(err?.message || 'Error al crear sesión demo');
setError(err?.message || t('demo:errors.creating_session', 'Error al crear sesión demo'));
console.error('Error creating demo session:', err);
setCreatingSession(false);
}
@@ -176,7 +178,7 @@ export const DemoPage: React.FC = () => {
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-[var(--bg-primary)] via-[var(--bg-secondary)] to-[var(--color-primary)]/5">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[var(--color-primary)] mx-auto"></div>
<p className="mt-4 text-[var(--text-secondary)]">Cargando cuentas demo...</p>
<p className="mt-4 text-[var(--text-secondary)]">{t('demo:loading.initial', 'Cargando cuentas demo...')}</p>
</div>
</div>
</PublicLayout>
@@ -200,31 +202,31 @@ export const DemoPage: React.FC = () => {
<div className="mb-6">
<span className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-[var(--color-primary)]/10 text-[var(--color-primary)]">
<Play className="w-4 h-4 mr-2" />
Demo Interactiva
{t('demo:hero.badge', 'Demo Interactiva')}
</span>
</div>
<h1 className="text-4xl tracking-tight font-extrabold text-[var(--text-primary)] sm:text-5xl lg:text-6xl">
<span className="block">Prueba El Panadero Digital</span>
<span className="block text-[var(--color-primary)]">sin compromiso</span>
<span className="block">{t('demo:hero.title', 'Prueba El Panadero Digital')}</span>
<span className="block text-[var(--color-primary)]">{t('demo:hero.subtitle', 'sin compromiso')}</span>
</h1>
<p className="mt-6 max-w-3xl mx-auto text-lg text-[var(--text-secondary)] sm:text-xl">
Elige el tipo de panadería que se ajuste a tu negocio
{t('demo:hero.description', 'Elige el tipo de panadería que se ajuste a tu negocio')}
</p>
<div className="mt-8 flex items-center justify-center space-x-6 text-sm text-[var(--text-tertiary)]">
<div className="flex items-center">
<Check className="w-4 h-4 text-green-500 mr-2" />
Sin tarjeta de crédito
{t('demo:hero.benefits.no_credit_card', 'Sin tarjeta de crédito')}
</div>
<div className="flex items-center">
<Clock className="w-4 h-4 text-green-500 mr-2" />
30 minutos de acceso
{t('demo:hero.benefits.access_time', '30 minutos de acceso')}
</div>
<div className="flex items-center">
<Shield className="w-4 h-4 text-green-500 mr-2" />
Datos reales en español
{t('demo:hero.benefits.real_data', 'Datos reales en español')}
</div>
</div>
</div>
@@ -258,18 +260,18 @@ export const DemoPage: React.FC = () => {
<div className="ml-4">
<h2 className="text-2xl font-bold text-[var(--text-primary)]">
{account.account_type === 'individual_bakery'
? 'Panadería Individual con Producción local'
: 'Panadería Franquiciada con Obrador Central'}
? t('demo:accounts.individual_bakery.title', 'Panadería Individual con Producción local')
: t('demo:accounts.central_baker.title', 'Panadería Franquiciada con Obrador Central')}
</h2>
<p className="text-sm text-[var(--text-tertiary)] mt-1">
{account.account_type === 'individual_bakery'
? account.business_model
: 'Punto de Venta + Obrador Central'}
? t('demo:accounts.individual_bakery.subtitle', account.business_model)
: t('demo:accounts.central_baker.subtitle', 'Punto de Venta + Obrador Central')}
</p>
</div>
</div>
<span className="px-3 py-1 bg-[var(--color-primary)]/10 text-[var(--color-primary)] rounded-full text-xs font-semibold">
DEMO
{t('demo:accounts.demo_badge', 'DEMO')}
</span>
</div>
@@ -281,45 +283,47 @@ export const DemoPage: React.FC = () => {
{/* Key Characteristics */}
<div className="mb-6 p-4 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-default)]">
<p className="text-xs font-semibold text-[var(--text-tertiary)] uppercase mb-3">
Características del negocio
{account.account_type === 'individual_bakery'
? t('demo:accounts.individual_bakery.characteristics.title', 'Características del negocio')
: t('demo:accounts.central_baker.characteristics.title', 'Características del negocio')}
</p>
<div className="grid grid-cols-2 gap-3 text-sm">
{account.account_type === 'individual_bakery' ? (
<>
<div>
<span className="text-[var(--text-tertiary)]">Empleados:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">~8</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.individual_bakery.characteristics.employees', 'Empleados')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.individual_bakery.characteristics.employees_value', '~8')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Turnos:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">1/día</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.individual_bakery.characteristics.shifts', 'Turnos')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.individual_bakery.characteristics.shifts_value', '1/día')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Ventas:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">Directas</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.individual_bakery.characteristics.sales', 'Ventas')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.individual_bakery.characteristics.sales_value', 'Directas')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Productos:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">Local</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.individual_bakery.characteristics.products', 'Productos')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.individual_bakery.characteristics.products_value', 'Local')}</span>
</div>
</>
) : (
<>
<div>
<span className="text-[var(--text-tertiary)]">Empleados:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">~5-6</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.central_baker.characteristics.employees', 'Empleados')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.central_baker.characteristics.employees_value', '~5-6')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Turnos:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">2/día</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.central_baker.characteristics.shifts', 'Turnos')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.central_baker.characteristics.shifts_value', '2/día')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Modelo:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">Franquicia</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.central_baker.characteristics.model', 'Modelo')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.central_baker.characteristics.model_value', 'Franquicia')}</span>
</div>
<div>
<span className="text-[var(--text-tertiary)]">Productos:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">De obrador</span>
<span className="text-[var(--text-tertiary)]">{t('demo:accounts.central_baker.characteristics.products', 'Productos')}:</span>
<span className="ml-2 font-semibold text-[var(--text-primary)]">{t('demo:accounts.central_baker.characteristics.products_value', 'De obrador')}</span>
</div>
</>
)}
@@ -330,7 +334,7 @@ export const DemoPage: React.FC = () => {
{account.features && account.features.length > 0 && (
<div className="mb-8 space-y-2">
<p className="text-sm font-semibold text-[var(--text-primary)] mb-3">
Funcionalidades incluidas:
{t('demo:accounts.features_title', 'Funcionalidades incluidas:')}
</p>
{account.features.map((feature, idx) => (
<div key={idx} className="flex items-center text-sm text-[var(--text-secondary)]">
@@ -349,7 +353,7 @@ export const DemoPage: React.FC = () => {
className="w-full bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-primary-dark)] hover:from-[var(--color-primary-dark)] hover:to-[var(--color-primary)] text-white shadow-lg hover:shadow-2xl transform hover:scale-[1.02] transition-all duration-200 font-semibold text-base py-4"
>
<Play className="mr-2 w-5 h-5" />
Iniciar Demo
{t('demo:accounts.start_demo', 'Iniciar Demo')}
<ArrowRight className="ml-2 w-5 h-5" />
</Button>
</div>
@@ -361,13 +365,13 @@ export const DemoPage: React.FC = () => {
{/* Footer CTA */}
<div className="mt-16 text-center">
<p className="text-[var(--text-secondary)] mb-4">
¿Ya tienes una cuenta?
{t('demo:footer.have_account', '¿Ya tienes una cuenta?')}
</p>
<Link
to="/login"
className="inline-flex items-center text-[var(--color-primary)] hover:text-[var(--color-primary-dark)] font-semibold transition-colors"
>
Inicia sesión aquí
{t('demo:footer.login_link', 'Inicia sesión aquí')}
<ArrowRight className="ml-2 w-4 h-4" />
</Link>
</div>
@@ -392,12 +396,14 @@ export const DemoPage: React.FC = () => {
</div>
<h2 className="text-2xl font-bold text-[var(--text-primary)] mb-2">
{progressPercentage >= 100 ? '¡Listo! Redirigiendo...' : 'Preparando tu Demo'}
{progressPercentage >= 100
? t('demo:loading.ready_title', '¡Listo! Redirigiendo...')
: t('demo:loading.preparing_title', 'Preparando tu Demo')}
</h2>
<p className="text-[var(--text-secondary)] mb-6">
{progressPercentage >= 100
? 'Tu entorno está listo. Accediendo al dashboard...'
: 'Configurando tu entorno personalizado con datos de muestra...'}
? t('demo:loading.ready_description', 'Tu entorno está listo. Accediendo al dashboard...')
: t('demo:loading.preparing_description', 'Configurando tu entorno personalizado con datos de muestra...')}
</p>
{/* Progress bar */}
@@ -412,7 +418,7 @@ export const DemoPage: React.FC = () => {
{progressPercentage < 100 && (
<div className="flex items-center justify-center text-sm text-[var(--text-tertiary)] mb-4">
<Clock className="w-4 h-4 mr-2" />
<span>Tiempo estimado: ~{estimatedTime}s</span>
<span>{t('demo:loading.estimated_time', 'Tiempo estimado: ~{{seconds}}s', { seconds: estimatedTime })}</span>
</div>
)}
@@ -420,7 +426,7 @@ export const DemoPage: React.FC = () => {
{progressPercentage < 100 && (
<div className="mt-2 p-4 bg-[var(--color-primary)]/5 rounded-lg border border-[var(--color-primary)]/20">
<p className="text-xs text-[var(--text-secondary)] italic">
💡 Tip: La demo incluye datos reales de panaderías españolas para que puedas explorar todas las funcionalidades
{t('demo:loading.tip', '💡 Tip: La demo incluye datos reales de panaderías españolas para que puedas explorar todas las funcionalidades')}
</p>
</div>
)}

View File

@@ -45,7 +45,7 @@ import {
} from 'lucide-react';
const FeaturesPage: React.FC = () => {
const { t } = useTranslation();
const { t } = useTranslation('features');
const navigate = useNavigate();
// Automatic System Timeline Steps
@@ -53,66 +53,66 @@ const FeaturesPage: React.FC = () => {
{
id: 'step1',
number: 1,
title: t('features:automatic.step1.title', 'Revisa Todo Tu Inventario'),
title: t('automatic.step1.title', 'Revisa Todo Tu Inventario'),
color: 'blue',
items: [
t('features:automatic.step1.item1', 'Cuenta cada kilo de harina, cada litro de leche'),
t('features:automatic.step1.item2', 'Comprueba fechas de caducidad'),
t('features:automatic.step1.item3', 'Ve qué llega hoy de proveedores'),
t('automatic.step1.item1', 'Cuenta cada kilo de harina, cada litro de leche'),
t('automatic.step1.item2', 'Comprueba fechas de caducidad'),
t('automatic.step1.item3', 'Ve qué llega hoy de proveedores'),
],
},
{
id: 'step2',
number: 2,
title: t('features:automatic.step2.title', 'Predice Ventas de Hoy'),
title: t('automatic.step2.title', 'Predice Ventas de Hoy'),
color: 'purple',
items: [
t('features:automatic.step2.item1', 'Analiza el día (lunes lluvioso, fiesta local, colegio cerrado)'),
t('features:automatic.step2.item2', 'Compara con días similares del pasado'),
t('features:automatic.step2.item3', 'Te dice: "Hoy venderás 80 croissants, 120 barras, 50 magdalenas"'),
t('automatic.step2.item1', 'Analiza el día (lunes lluvioso, fiesta local, colegio cerrado)'),
t('automatic.step2.item2', 'Compara con días similares del pasado'),
t('automatic.step2.item3', 'Te dice: "Hoy venderás 80 croissants, 120 barras, 50 magdalenas"'),
],
},
{
id: 'step3',
number: 3,
title: t('features:automatic.step3.title', 'Planifica Qué Hacer'),
title: t('automatic.step3.title', 'Planifica Qué Hacer'),
color: 'green',
items: [
t('features:automatic.step3.item1', 'Calcula exactamente cuánto hornear'),
t('features:automatic.step3.item2', 'Te da una lista lista para ejecutar'),
t('features:automatic.step3.item3', '"Haz 80 croissants (no 100), usa 5kg mantequilla, 3kg harina..."'),
t('automatic.step3.item1', 'Calcula exactamente cuánto hornear'),
t('automatic.step3.item2', 'Te da una lista lista para ejecutar'),
t('automatic.step3.item3', '"Haz 80 croissants (no 100), usa 5kg mantequilla, 3kg harina..."'),
],
},
{
id: 'step4',
number: 4,
title: t('features:automatic.step4.title', 'Gestiona Inventario Inteligentemente'),
title: t('automatic.step4.title', 'Gestiona Inventario Inteligentemente'),
color: 'amber',
items: [
t('features:automatic.step4.projection_title', 'Proyecta 7 días hacia adelante:'),
t('features:automatic.step4.solution', '"Pide 50kg hoy, llega en 3 días, problema resuelto"'),
t('automatic.step4.projection_title', 'Proyecta 7 días hacia adelante:'),
t('automatic.step4.solution', '"Pide 50kg hoy, llega en 3 días, problema resuelto"'),
],
},
{
id: 'step5',
number: 5,
title: t('features:automatic.step5.title', 'Crea Pedidos a Proveedores'),
title: t('automatic.step5.title', 'Crea Pedidos a Proveedores'),
color: 'red',
items: [
t('features:automatic.step5.item1', 'Sabe que Proveedor A tarda 3 días, Proveedor B tarda 5'),
t('features:automatic.step5.item2', 'Calcula cuándo pedir para que llegue justo a tiempo'),
t('features:automatic.step5.item3', 'Prepara pedidos listos para aprobar con 1 clic'),
t('automatic.step5.item1', 'Sabe que Proveedor A tarda 3 días, Proveedor B tarda 5'),
t('automatic.step5.item2', 'Calcula cuándo pedir para que llegue justo a tiempo'),
t('automatic.step5.item3', 'Prepara pedidos listos para aprobar con 1 clic'),
],
},
{
id: 'step6',
number: 6,
title: t('features:automatic.step6.title', 'Previene Desperdicios'),
title: t('automatic.step6.title', 'Previene Desperdicios'),
color: 'teal',
items: [
t('features:automatic.step6.item1', '"Tienes leche que caduca en 5 días"'),
t('features:automatic.step6.item2', '"Solo usarás 15L en 5 días"'),
t('features:automatic.step6.item3', '"No pidas más de 15L, se desperdiciará"'),
t('automatic.step6.item1', '"Tienes leche que caduca en 5 días"'),
t('automatic.step6.item2', '"Solo usarás 15L en 5 días"'),
t('automatic.step6.item3', '"No pidas más de 15L, se desperdiciará"'),
],
},
];
@@ -121,32 +121,32 @@ const FeaturesPage: React.FC = () => {
const tocSections: TOCSection[] = [
{
id: 'automatic-system',
label: t('features:toc.automatic', 'Sistema Automático'),
label: t('toc.automatic', 'Sistema Automático'),
icon: <Clock className="w-4 h-4" />
},
{
id: 'local-intelligence',
label: t('features:toc.local', 'Inteligencia Local'),
label: t('toc.local', 'Inteligencia Local'),
icon: <MapPin className="w-4 h-4" />
},
{
id: 'demand-forecasting',
label: t('features:toc.forecasting', 'Predicción de Demanda'),
label: t('toc.forecasting', 'Predicción de Demanda'),
icon: <Target className="w-4 h-4" />
},
{
id: 'waste-reduction',
label: t('features:toc.waste', 'Reducción de Desperdicios'),
label: t('toc.waste', 'Reducción de Desperdicios'),
icon: <Recycle className="w-4 h-4" />
},
{
id: 'sustainability',
label: t('features:toc.sustainability', 'Sostenibilidad'),
label: t('toc.sustainability', 'Sostenibilidad'),
icon: <Leaf className="w-4 h-4" />
},
{
id: 'business-models',
label: t('features:toc.business', 'Modelos de Negocio'),
label: t('toc.business', 'Modelos de Negocio'),
icon: <Store className="w-4 h-4" />
},
];
@@ -167,7 +167,7 @@ const FeaturesPage: React.FC = () => {
{/* Floating CTA */}
<FloatingCTA
text={t('features:cta.button', 'Solicitar Demo')}
text={t('cta.button', 'Solicitar Demo')}
onClick={() => navigate(getDemoUrl())}
icon={<ArrowRight className="w-4 h-4" />}
position="bottom-right"
@@ -190,10 +190,10 @@ const FeaturesPage: React.FC = () => {
<ScrollReveal variant="fadeUp" delay={0.1}>
<div className="text-center max-w-4xl mx-auto">
<h1 className="text-4xl lg:text-6xl font-extrabold text-[var(--text-primary)] mb-6">
{t('features:hero.title', 'Cómo Bakery-IA Trabaja Para Ti Cada Día')}
{t('hero.title', 'Cómo Bakery-IA Trabaja Para Ti Cada Día')}
</h1>
<p className="text-xl text-[var(--text-secondary)] leading-relaxed">
{t('features:hero.subtitle', 'Todas las funcionalidades explicadas en lenguaje sencillo para dueños de panaderías')}
{t('hero.subtitle', 'Todas las funcionalidades explicadas en lenguaje sencillo para dueños de panaderías')}
</p>
</div>
</ScrollReveal>
@@ -207,13 +207,13 @@ const FeaturesPage: React.FC = () => {
<div className="text-center mb-16">
<div className="inline-flex items-center gap-2 bg-[var(--color-primary)]/10 text-[var(--color-primary)] px-4 py-2 rounded-full text-sm font-medium mb-6">
<Clock className="w-4 h-4" />
<span>{t('features:automatic.badge', 'La Funcionalidad Estrella')}</span>
<span>{t('automatic.badge', 'La Funcionalidad Estrella')}</span>
</div>
<h2 className="text-3xl lg:text-5xl font-extrabold text-[var(--text-primary)] mb-6">
{t('features:automatic.title', 'Tu Asistente Personal Que Nunca Duerme')}
{t('automatic.title', 'Tu Asistente Personal Que Nunca Duerme')}
</h2>
<p className="text-xl text-[var(--text-secondary)] max-w-3xl mx-auto">
{t('features:automatic.intro', 'Imagina contratar un ayudante súper organizado que llega a las 5:30 AM (antes que tú) y hace todo esto AUTOMÁTICAMENTE:')}
{t('automatic.intro', 'Imagina contratar un ayudante súper organizado que llega a las 5:30 AM (antes que tú) y hace todo esto AUTOMÁTICAMENTE:')}
</p>
</div>
</ScrollReveal>
@@ -233,24 +233,24 @@ const FeaturesPage: React.FC = () => {
<div className="text-center max-w-3xl mx-auto">
<Clock className="w-16 h-16 mx-auto mb-4" />
<h3 className="text-2xl lg:text-3xl font-bold mb-4">
{t('features:automatic.result.title', 'A las 6:00 AM recibes un email:')}
{t('automatic.result.title', 'A las 6:00 AM recibes un email:')}
</h3>
<div className="space-y-2 text-lg">
<div className="flex items-center justify-center gap-2">
<CheckCircle2 className="w-6 h-6" />
<span>{t('features:automatic.result.item1', 'Predicción del día hecha')}</span>
<span>{t('automatic.result.item1', 'Predicción del día hecha')}</span>
</div>
<div className="flex items-center justify-center gap-2">
<CheckCircle2 className="w-6 h-6" />
<span>{t('features:automatic.result.item2', 'Plan de producción listo')}</span>
<span>{t('automatic.result.item2', 'Plan de producción listo')}</span>
</div>
<div className="flex items-center justify-center gap-2">
<CheckCircle2 className="w-6 h-6" />
<span>{t('features:automatic.result.item3', '3 pedidos creados (aprobar con 1 clic)')}</span>
<span>{t('automatic.result.item3', '3 pedidos creados (aprobar con 1 clic)')}</span>
</div>
<div className="flex items-center justify-center gap-2">
<CheckCircle2 className="w-6 h-6" />
<span>{t('features:automatic.result.item4', 'Alerta: "Leche caduca en 2 días, úsala primero"')}</span>
<span>{t('automatic.result.item4', 'Alerta: "Leche caduca en 2 días, úsala primero"')}</span>
</div>
</div>
</div>
@@ -259,32 +259,32 @@ const FeaturesPage: React.FC = () => {
{/* What it eliminates */}
<div className="bg-[var(--bg-secondary)] rounded-2xl p-8 border border-[var(--border-primary)]">
<h3 className="text-2xl font-bold text-[var(--text-primary)] mb-6 text-center">
{t('features:automatic.eliminates.title', 'Lo que ELIMINA de tu rutina:')}
{t('automatic.eliminates.title', 'Lo que ELIMINA de tu rutina:')}
</h3>
<div className="grid md:grid-cols-2 gap-4">
<div className="flex items-start gap-3">
<span className="text-red-500 text-xl"></span>
<span className="text-[var(--text-secondary)]">{t('features:automatic.eliminates.item1', 'Adivinar cuánto hacer')}</span>
<span className="text-[var(--text-secondary)]">{t('automatic.eliminates.item1', 'Adivinar cuánto hacer')}</span>
</div>
<div className="flex items-start gap-3">
<span className="text-red-500 text-xl"></span>
<span className="text-[var(--text-secondary)]">{t('features:automatic.eliminates.item2', 'Contar inventario manualmente')}</span>
<span className="text-[var(--text-secondary)]">{t('automatic.eliminates.item2', 'Contar inventario manualmente')}</span>
</div>
<div className="flex items-start gap-3">
<span className="text-red-500 text-xl"></span>
<span className="text-[var(--text-secondary)]">{t('features:automatic.eliminates.item3', 'Calcular cuándo pedir a proveedores')}</span>
<span className="text-[var(--text-secondary)]">{t('automatic.eliminates.item3', 'Calcular cuándo pedir a proveedores')}</span>
</div>
<div className="flex items-start gap-3">
<span className="text-red-500 text-xl"></span>
<span className="text-[var(--text-secondary)]">{t('features:automatic.eliminates.item4', 'Recordar fechas de caducidad')}</span>
<span className="text-[var(--text-secondary)]">{t('automatic.eliminates.item4', 'Recordar fechas de caducidad')}</span>
</div>
<div className="flex items-start gap-3">
<span className="text-red-500 text-xl"></span>
<span className="text-[var(--text-secondary)]">{t('features:automatic.eliminates.item5', 'Preocuparte por quedarte sin stock')}</span>
<span className="text-[var(--text-secondary)]">{t('automatic.eliminates.item5', 'Preocuparte por quedarte sin stock')}</span>
</div>
<div className="flex items-start gap-3">
<span className="text-red-500 text-xl"></span>
<span className="text-[var(--text-secondary)]">{t('features:automatic.eliminates.item6', 'Desperdiciar ingredientes caducados')}</span>
<span className="text-[var(--text-secondary)]">{t('automatic.eliminates.item6', 'Desperdiciar ingredientes caducados')}</span>
</div>
</div>
</div>
@@ -300,13 +300,13 @@ const FeaturesPage: React.FC = () => {
<div className="text-center mb-16">
<div className="inline-flex items-center gap-2 bg-[var(--color-primary)]/10 text-[var(--color-primary)] px-4 py-2 rounded-full text-sm font-medium mb-6">
<MapPin className="w-4 h-4" />
<span>{t('features:local.badge', 'Tu Ventaja Competitiva')}</span>
<span>{t('local.badge', 'Tu Ventaja Competitiva')}</span>
</div>
<h2 className="text-3xl lg:text-5xl font-extrabold text-[var(--text-primary)] mb-6">
{t('features:local.title', 'Tu Panadería Es Única. La IA También.')}
{t('local.title', 'Tu Panadería Es Única. La IA También.')}
</h2>
<p className="text-xl text-[var(--text-secondary)] max-w-3xl mx-auto">
{t('features:local.intro', 'Las IA genéricas saben que es lunes. La TUYA sabe que:')}
{t('local.intro', 'Las IA genéricas saben que es lunes. La TUYA sabe que:')}
</p>
</div>
</ScrollReveal>
@@ -319,20 +319,20 @@ const FeaturesPage: React.FC = () => {
<School className="w-6 h-6 text-blue-600" />
</div>
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-3">
{t('features:local.schools.title', 'Colegios Cerca')}
{t('local.schools.title', 'Colegios Cerca')}
</h3>
<ul className="space-y-2 text-[var(--text-secondary)]">
<li className="flex items-start gap-2">
<span className="text-blue-600 mt-0.5"></span>
<span>{t('features:local.schools.item1', '"El CEIP San José está a 200m"')}</span>
<span>{t('local.schools.item1', '"El CEIP San José está a 200m"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-blue-600 mt-0.5"></span>
<span>{t('features:local.schools.item2', '"En agosto venden 40% menos (vacaciones escolares)"')}</span>
<span>{t('local.schools.item2', '"En agosto venden 40% menos (vacaciones escolares)"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-blue-600 mt-0.5"></span>
<span>{t('features:local.schools.item3', '"Los lunes a las 8:30 hay pico (padres tras dejar niños)"')}</span>
<span>{t('local.schools.item3', '"Los lunes a las 8:30 hay pico (padres tras dejar niños)"')}</span>
</li>
</ul>
</div>
@@ -345,20 +345,20 @@ const FeaturesPage: React.FC = () => {
<Building2 className="w-6 h-6 text-purple-600" />
</div>
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-3">
{t('features:local.offices.title', 'Oficinas y Empresas')}
{t('local.offices.title', 'Oficinas y Empresas')}
</h3>
<ul className="space-y-2 text-[var(--text-secondary)]">
<li className="flex items-start gap-2">
<span className="text-purple-600 mt-0.5"></span>
<span>{t('features:local.offices.item1', '"Edificio de oficinas a 150m (250 trabajadores)"')}</span>
<span>{t('local.offices.item1', '"Edificio de oficinas a 150m (250 trabajadores)"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-purple-600 mt-0.5"></span>
<span>{t('features:local.offices.item2', '"Viernes venden menos al mediodía (teletrabajo)"')}</span>
<span>{t('local.offices.item2', '"Viernes venden menos al mediodía (teletrabajo)"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-purple-600 mt-0.5"></span>
<span>{t('features:local.offices.item3', '"Hora punta: 13:00-14:00 (bocadillos)"')}</span>
<span>{t('local.offices.item3', '"Hora punta: 13:00-14:00 (bocadillos)"')}</span>
</li>
</ul>
</div>
@@ -371,20 +371,20 @@ const FeaturesPage: React.FC = () => {
<Dumbbell className="w-6 h-6 text-green-600" />
</div>
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-3">
{t('features:local.gyms.title', 'Centros Deportivos')}
{t('local.gyms.title', 'Centros Deportivos')}
</h3>
<ul className="space-y-2 text-[var(--text-secondary)]">
<li className="flex items-start gap-2">
<span className="text-green-600 mt-0.5"></span>
<span>{t('features:local.gyms.item1', '"Gimnasio a 300m"')}</span>
<span>{t('local.gyms.item1', '"Gimnasio a 300m"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-green-600 mt-0.5"></span>
<span>{t('features:local.gyms.item2', '"Mayor venta de productos saludables (pan integral, barritas)"')}</span>
<span>{t('local.gyms.item2', '"Mayor venta de productos saludables (pan integral, barritas)"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-green-600 mt-0.5"></span>
<span>{t('features:local.gyms.item3', '"Pico a las 7:00 AM y 19:00 PM"')}</span>
<span>{t('local.gyms.item3', '"Pico a las 7:00 AM y 19:00 PM"')}</span>
</li>
</ul>
</div>
@@ -397,20 +397,20 @@ const FeaturesPage: React.FC = () => {
<ShoppingBag className="w-6 h-6 text-amber-600" />
</div>
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-3">
{t('features:local.competition.title', 'Tu Competencia')}
{t('local.competition.title', 'Tu Competencia')}
</h3>
<ul className="space-y-2 text-[var(--text-secondary)]">
<li className="flex items-start gap-2">
<span className="text-amber-600 mt-0.5"></span>
<span>{t('features:local.competition.item1', '"Otra panadería abrió hace 2 meses a 500m"')}</span>
<span>{t('local.competition.item1', '"Otra panadería abrió hace 2 meses a 500m"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-amber-600 mt-0.5"></span>
<span>{t('features:local.competition.item2', '"Impacto: -15% en ventas de pan básico"')}</span>
<span>{t('local.competition.item2', '"Impacto: -15% en ventas de pan básico"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-amber-600 mt-0.5"></span>
<span>{t('features:local.competition.item3', '"Oportunidad: Diferénciate con especialidades"')}</span>
<span>{t('local.competition.item3', '"Oportunidad: Diferénciate con especialidades"')}</span>
</li>
</ul>
</div>
@@ -423,20 +423,20 @@ const FeaturesPage: React.FC = () => {
<Cloud className="w-6 h-6 text-sky-600" />
</div>
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-3">
{t('features:local.weather.title', 'Clima de Tu Zona')}
{t('local.weather.title', 'Clima de Tu Zona')}
</h3>
<ul className="space-y-2 text-[var(--text-secondary)]">
<li className="flex items-start gap-2">
<span className="text-sky-600 mt-0.5"></span>
<span>{t('features:local.weather.item1', '"Datos AEMET de tu código postal"')}</span>
<span>{t('local.weather.item1', '"Datos AEMET de tu código postal"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-sky-600 mt-0.5"></span>
<span>{t('features:local.weather.item2', '"Lluvia → -20% croissants, +10% pan de molde"')}</span>
<span>{t('local.weather.item2', '"Lluvia → -20% croissants, +10% pan de molde"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-sky-600 mt-0.5"></span>
<span>{t('features:local.weather.item3', '"Calor → +30% productos frescos"')}</span>
<span>{t('local.weather.item3', '"Calor → +30% productos frescos"')}</span>
</li>
</ul>
</div>
@@ -449,20 +449,20 @@ const FeaturesPage: React.FC = () => {
<PartyPopper className="w-6 h-6 text-pink-600" />
</div>
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-3">
{t('features:local.events.title', 'Eventos Locales')}
{t('local.events.title', 'Eventos Locales')}
</h3>
<ul className="space-y-2 text-[var(--text-secondary)]">
<li className="flex items-start gap-2">
<span className="text-pink-600 mt-0.5"></span>
<span>{t('features:local.events.item1', '"Mercadillo los viernes en Plaza Mayor (500m)"')}</span>
<span>{t('local.events.item1', '"Mercadillo los viernes en Plaza Mayor (500m)"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-pink-600 mt-0.5"></span>
<span>{t('features:local.events.item2', '"Fiestas del barrio próxima semana"')}</span>
<span>{t('local.events.item2', '"Fiestas del barrio próxima semana"')}</span>
</li>
<li className="flex items-start gap-2">
<span className="text-pink-600 mt-0.5"></span>
<span>{t('features:local.events.item3', '"Partido importante → pico de ventas pre-evento"')}</span>
<span>{t('local.events.item3', '"Partido importante → pico de ventas pre-evento"')}</span>
</li>
</ul>
</div>
@@ -473,16 +473,16 @@ const FeaturesPage: React.FC = () => {
<ScrollReveal variant="fadeUp" delay={0.4}>
<div className="mt-12 max-w-4xl mx-auto bg-gradient-to-r from-[var(--color-primary)] to-orange-600 rounded-2xl p-8 text-white">
<h3 className="text-2xl font-bold mb-4 text-center">
{t('features:local.why_matters.title', 'Por qué importa:')}
{t('local.why_matters.title', 'Por qué importa:')}
</h3>
<div className="grid md:grid-cols-2 gap-6">
<div className="bg-white/10 rounded-lg p-4">
<p className="font-medium mb-2">{t('features:local.why_matters.generic', 'IA genérica:')}</p>
<p className="text-white/90">{t('features:local.why_matters.generic_example', '"Es lunes → vende X"')}</p>
<p className="font-medium mb-2">{t('local.why_matters.generic', 'IA genérica:')}</p>
<p className="text-white/90">{t('local.why_matters.generic_example', '"Es lunes → vende X"')}</p>
</div>
<div className="bg-white/20 rounded-lg p-4 border-2 border-white">
<p className="font-medium mb-2">{t('features:local.why_matters.yours', 'TU IA:')}</p>
<p className="text-white/90">{t('features:local.why_matters.yours_example', '"Es lunes, llueve, colegio cerrado (festivo local), mercadillo cancelado → vende Y"')}</p>
<p className="font-medium mb-2">{t('local.why_matters.yours', 'TU IA:')}</p>
<p className="text-white/90">{t('local.why_matters.yours_example', '"Es lunes, llueve, colegio cerrado (festivo local), mercadillo cancelado → vende Y"')}</p>
</div>
</div>
<p className="text-center mt-6 text-xl font-bold">
@@ -502,7 +502,7 @@ const FeaturesPage: React.FC = () => {
Sabe Cuánto Venderás Mañana (<AnimatedCounter value={92} suffix="%" className="inline text-[var(--color-primary)]" /> de Precisión)
</h2>
<p className="text-xl text-[var(--text-secondary)] max-w-3xl mx-auto">
{t('features:forecasting.subtitle', 'No es magia. Es matemáticas con tus datos.')}
{t('forecasting.subtitle', 'No es magia. Es matemáticas con tus datos.')}
</p>
</div>
</ScrollReveal>
@@ -510,59 +510,59 @@ const FeaturesPage: React.FC = () => {
<div className="max-w-5xl mx-auto">
<div className="bg-gradient-to-br from-blue-50 to-indigo-50 dark:from-blue-900/20 dark:to-indigo-900/20 rounded-2xl p-8 border-2 border-blue-200 dark:border-blue-800 mb-8">
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-4">
{t('features:forecasting.learns_from.title', 'La IA aprende de:')}
{t('forecasting.learns_from.title', 'La IA aprende de:')}
</h3>
<div className="grid md:grid-cols-2 gap-4">
<div className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:forecasting.learns_from.item1', 'Tus ventas pasadas (6-12 meses)')}</span>
<span className="text-[var(--text-secondary)]">{t('forecasting.learns_from.item1', 'Tus ventas pasadas (6-12 meses)')}</span>
</div>
<div className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:forecasting.learns_from.item2', 'Día de la semana (lunes ≠ sábado)')}</span>
<span className="text-[var(--text-secondary)]">{t('forecasting.learns_from.item2', 'Día de la semana (lunes ≠ sábado)')}</span>
</div>
<div className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:forecasting.learns_from.item3', 'Estacionalidad (agosto ≠ diciembre)')}</span>
<span className="text-[var(--text-secondary)]">{t('forecasting.learns_from.item3', 'Estacionalidad (agosto ≠ diciembre)')}</span>
</div>
<div className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:forecasting.learns_from.item4', 'Clima local (lluvia, calor, frío)')}</span>
<span className="text-[var(--text-secondary)]">{t('forecasting.learns_from.item4', 'Clima local (lluvia, calor, frío)')}</span>
</div>
<div className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:forecasting.learns_from.item5', 'Eventos y festivos')}</span>
<span className="text-[var(--text-secondary)]">{t('forecasting.learns_from.item5', 'Eventos y festivos')}</span>
</div>
<div className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:forecasting.learns_from.item6', 'Tu entorno único')}</span>
<span className="text-[var(--text-secondary)]">{t('forecasting.learns_from.item6', 'Tu entorno único')}</span>
</div>
</div>
</div>
<div className="bg-white dark:bg-gray-800 rounded-2xl p-8 border-2 border-[var(--color-primary)] shadow-lg">
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-4">
{t('features:forecasting.result.title', 'Resultado:')}
{t('forecasting.result.title', 'Resultado:')}
</h3>
<p className="text-[var(--text-secondary)] mb-4">
{t('features:forecasting.result.intro', 'Mañana (martes 15 de marzo) venderás:')}
{t('forecasting.result.intro', 'Mañana (martes 15 de marzo) venderás:')}
</p>
<div className="space-y-3">
<div className="flex justify-between items-center bg-[var(--bg-secondary)] rounded-lg p-4">
<span className="font-medium">{t('features:forecasting.result.croissants', '78-82 croissants')}</span>
<span className="text-[var(--color-primary)] font-bold">{t('features:forecasting.result.croissants_avg', '(80 ±2)')}</span>
<span className="font-medium">{t('forecasting.result.croissants', '78-82 croissants')}</span>
<span className="text-[var(--color-primary)] font-bold">{t('forecasting.result.croissants_avg', '(80 ±2)')}</span>
</div>
<div className="flex justify-between items-center bg-[var(--bg-secondary)] rounded-lg p-4">
<span className="font-medium">{t('features:forecasting.result.loaves', '115-125 barras')}</span>
<span className="text-[var(--color-primary)] font-bold">{t('features:forecasting.result.loaves_avg', '(120 ±5)')}</span>
<span className="font-medium">{t('forecasting.result.loaves', '115-125 barras')}</span>
<span className="text-[var(--color-primary)] font-bold">{t('forecasting.result.loaves_avg', '(120 ±5)')}</span>
</div>
<div className="flex justify-between items-center bg-[var(--bg-secondary)] rounded-lg p-4">
<span className="font-medium">{t('features:forecasting.result.muffins', '45-50 magdalenas')}</span>
<span className="text-[var(--color-primary)] font-bold">{t('features:forecasting.result.muffins_avg', '(48 ±2)')}</span>
<span className="font-medium">{t('forecasting.result.muffins', '45-50 magdalenas')}</span>
<span className="text-[var(--color-primary)] font-bold">{t('forecasting.result.muffins_avg', '(48 ±2)')}</span>
</div>
</div>
<p className="mt-4 text-sm text-[var(--text-secondary)]">
{t('features:forecasting.confidence', 'Confianza: 92% de las veces acierta dentro del rango')}
{t('forecasting.confidence', 'Confianza: 92% de las veces acierta dentro del rango')}
</p>
</div>
</div>
@@ -575,7 +575,7 @@ const FeaturesPage: React.FC = () => {
<ScrollReveal variant="fadeUp" delay={0.1}>
<div className="text-center mb-12">
<h2 className="text-3xl lg:text-4xl font-extrabold text-[var(--text-primary)] mb-4">
{t('features:waste.title', 'Menos Pan en la Basura, Más Dinero en Tu Bolsillo')}
{t('waste.title', 'Menos Pan en la Basura, Más Dinero en Tu Bolsillo')}
</h2>
</div>
</ScrollReveal>
@@ -588,14 +588,14 @@ const FeaturesPage: React.FC = () => {
<AlertTriangle className="w-6 h-6 text-red-600" />
</div>
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-4">
{t('features:waste.before.title', 'Ejemplo típico de panadería:')}
{t('waste.before.title', 'Ejemplo típico de panadería:')}
</h3>
<ul className="space-y-3 text-[var(--text-secondary)]">
<li>{t('features:waste.before.item1', 'Haces 50 barras de más cada día "por si acaso"')}</li>
<li>{t('features:waste.before.item2', 'Precio: €2/barra')}</li>
<li className="font-bold text-red-700 dark:text-red-400">{t('features:waste.before.daily', 'Desperdicio: 50 × €2 = €100/día')}</li>
<li className="font-bold text-red-700 dark:text-red-400">{t('features:waste.before.monthly', 'Al mes: €100 × 30 = €3,000 perdidos')}</li>
<li className="font-bold text-red-900 dark:text-red-300 text-lg">{t('features:waste.before.yearly', 'Al año: €36,000 tirados a la basura')}</li>
<li>{t('waste.before.item1', 'Haces 50 barras de más cada día "por si acaso"')}</li>
<li>{t('waste.before.item2', 'Precio: €2/barra')}</li>
<li className="font-bold text-red-700 dark:text-red-400">{t('waste.before.daily', 'Desperdicio: 50 × €2 = €100/día')}</li>
<li className="font-bold text-red-700 dark:text-red-400">{t('waste.before.monthly', 'Al mes: €100 × 30 = €3,000 perdidos')}</li>
<li className="font-bold text-red-900 dark:text-red-300 text-lg">{t('waste.before.yearly', 'Al año: €36,000 tirados a la basura')}</li>
</ul>
</div>
</ScrollReveal>
@@ -607,18 +607,18 @@ const FeaturesPage: React.FC = () => {
<TrendingUp className="w-6 h-6 text-green-600" />
</div>
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-4">
{t('features:waste.after.title', 'Con Bakery-IA:')}
{t('waste.after.title', 'Con Bakery-IA:')}
</h3>
<ul className="space-y-3 text-[var(--text-secondary)]">
<li>{t('features:waste.after.item1', 'Predicción precisa → Haces 5-10 barras de más (seguridad)')}</li>
<li>{t('features:waste.after.item2', 'Desperdicio: 5 × €2 = €10/día')}</li>
<li className="font-bold text-green-700 dark:text-green-400">{t('features:waste.after.monthly', 'Al mes: €300')}</li>
<li>{t('waste.after.item1', 'Predicción precisa → Haces 5-10 barras de más (seguridad)')}</li>
<li>{t('waste.after.item2', 'Desperdicio: 5 × €2 = €10/día')}</li>
<li className="font-bold text-green-700 dark:text-green-400">{t('waste.after.monthly', 'Al mes: €300')}</li>
<li className="font-bold text-green-900 dark:text-green-300 text-xl bg-green-100 dark:bg-green-900/40 p-3 rounded-lg">
AHORRO: <AnimatedCounter value={2700} prefix="€" className="inline" decimals={0} />/mes (<AnimatedCounter value={32400} prefix="€" className="inline" decimals={0} />/año)
</li>
</ul>
<p className="mt-4 text-sm font-medium text-green-700 dark:text-green-400">
{t('features:waste.after.roi', 'Recuperas la inversión en semana 1.')}
{t('waste.after.roi', 'Recuperas la inversión en semana 1.')}
</p>
</div>
</ScrollReveal>
@@ -646,10 +646,10 @@ const FeaturesPage: React.FC = () => {
<div className="text-center mb-12">
<div className="inline-flex items-center gap-2 bg-green-500/10 text-green-600 dark:text-green-400 px-4 py-2 rounded-full text-sm font-medium mb-6">
<Leaf className="w-4 h-4" />
<span>{t('features:sustainability.badge', 'Funcionalidad del Sistema')}</span>
<span>{t('sustainability.badge', 'Funcionalidad del Sistema')}</span>
</div>
<h2 className="text-3xl lg:text-4xl font-extrabold text-[var(--text-primary)] mb-4">
{t('features:sustainability.title', 'Impacto Ambiental y Sostenibilidad')}
{t('sustainability.title', 'Impacto Ambiental y Sostenibilidad')}
</h2>
</div>
</ScrollReveal>
@@ -663,14 +663,14 @@ const FeaturesPage: React.FC = () => {
</div>
<div>
<h3 className="text-2xl font-bold text-[var(--text-primary)] mb-3">
{t('features:sustainability.un_sdg.title', 'Cumplimiento Automático ODS 12.3 (ONU)')}
{t('sustainability.un_sdg.title', 'Cumplimiento Automático ODS 12.3 (ONU)')}
</h3>
<p className="text-[var(--text-secondary)] mb-4">
{t('features:sustainability.un_sdg.description', 'Sin hacer nada extra, cumples con el Objetivo de Desarrollo Sostenible 12.3 de Naciones Unidas (reducción desperdicio alimentario).')}
{t('sustainability.un_sdg.description', 'Sin hacer nada extra, cumples con el Objetivo de Desarrollo Sostenible 12.3 de Naciones Unidas (reducción desperdicio alimentario).')}
</p>
<div className="bg-white dark:bg-gray-800 rounded-lg p-4 border-l-4 border-blue-600">
<p className="font-medium text-[var(--text-primary)]">
{t('features:sustainability.un_sdg.benefit', 'Recibes certificación automática → Credibilidad con clientes')}
{t('sustainability.un_sdg.benefit', 'Recibes certificación automática → Credibilidad con clientes')}
</p>
</div>
</div>
@@ -681,7 +681,7 @@ const FeaturesPage: React.FC = () => {
{/* Sustainability Benefits */}
<div className="max-w-6xl mx-auto mb-12">
<h3 className="text-2xl font-bold text-[var(--text-primary)] mb-6 text-center">
{t('features:sustainability.benefits.title', 'Funcionalidades de Sostenibilidad:')}
{t('sustainability.benefits.title', 'Funcionalidades de Sostenibilidad:')}
</h3>
<div className="grid md:grid-cols-2 gap-6">
<div className="bg-[var(--bg-secondary)] rounded-xl p-6 border border-[var(--border-primary)]">
@@ -691,10 +691,10 @@ const FeaturesPage: React.FC = () => {
</div>
<div>
<h4 className="font-bold text-[var(--text-primary)] mb-2">
{t('features:sustainability.benefits.impact_tracking.title', 'Seguimiento de Impacto Ambiental')}
{t('sustainability.benefits.impact_tracking.title', 'Seguimiento de Impacto Ambiental')}
</h4>
<p className="text-sm text-[var(--text-secondary)]">
{t('features:sustainability.benefits.impact_tracking.description', 'Medición automática de CO₂, agua y desperdicio alimentario con métricas detalladas')}
{t('sustainability.benefits.impact_tracking.description', 'Medición automática de CO₂, agua y desperdicio alimentario con métricas detalladas')}
</p>
</div>
</div>
@@ -707,10 +707,10 @@ const FeaturesPage: React.FC = () => {
</div>
<div>
<h4 className="font-bold text-[var(--text-primary)] mb-2">
{t('features:sustainability.benefits.sdg_compliance.title', 'Cumplimiento ODS 12.3')}
{t('sustainability.benefits.sdg_compliance.title', 'Cumplimiento ODS 12.3')}
</h4>
<p className="text-sm text-[var(--text-secondary)]">
{t('features:sustainability.benefits.sdg_compliance.description', 'Seguimiento automático del cumplimiento de los Objetivos de Desarrollo Sostenible de la ONU')}
{t('sustainability.benefits.sdg_compliance.description', 'Seguimiento automático del cumplimiento de los Objetivos de Desarrollo Sostenible de la ONU')}
</p>
</div>
</div>
@@ -723,10 +723,10 @@ const FeaturesPage: React.FC = () => {
</div>
<div>
<h4 className="font-bold text-[var(--text-primary)] mb-2">
{t('features:sustainability.benefits.reporting.title', 'Informes de Sostenibilidad')}
{t('sustainability.benefits.reporting.title', 'Informes de Sostenibilidad')}
</h4>
<p className="text-sm text-[var(--text-secondary)]">
{t('features:sustainability.benefits.reporting.description', 'Generación automática de informes listos para auditorías y certificaciones ambientales')}
{t('sustainability.benefits.reporting.description', 'Generación automática de informes listos para auditorías y certificaciones ambientales')}
</p>
</div>
</div>
@@ -739,10 +739,10 @@ const FeaturesPage: React.FC = () => {
</div>
<div>
<h4 className="font-bold text-[var(--text-primary)] mb-2">
{t('features:sustainability.benefits.certification.title', 'Preparación para Certificaciones')}
{t('sustainability.benefits.certification.title', 'Preparación para Certificaciones')}
</h4>
<p className="text-sm text-[var(--text-secondary)]">
{t('features:sustainability.benefits.certification.description', 'Datos y documentación listos para solicitudes de certificaciones de sostenibilidad')}
{t('sustainability.benefits.certification.description', 'Datos y documentación listos para solicitudes de certificaciones de sostenibilidad')}
</p>
</div>
</div>
@@ -755,10 +755,10 @@ const FeaturesPage: React.FC = () => {
</div>
<div>
<h4 className="font-bold text-[var(--text-primary)] mb-2">
{t('features:sustainability.benefits.data_export.title', 'Exportación de Datos Ambientales')}
{t('sustainability.benefits.data_export.title', 'Exportación de Datos Ambientales')}
</h4>
<p className="text-sm text-[var(--text-secondary)]">
{t('features:sustainability.benefits.data_export.description', 'Exporta tus métricas de sostenibilidad en formatos estándar para reportes externos y auditorías')}
{t('sustainability.benefits.data_export.description', 'Exporta tus métricas de sostenibilidad en formatos estándar para reportes externos y auditorías')}
</p>
</div>
</div>
@@ -769,24 +769,24 @@ const FeaturesPage: React.FC = () => {
{/* How it works */}
<div className="max-w-4xl mx-auto bg-[var(--bg-secondary)] rounded-2xl p-8 border border-[var(--border-primary)]">
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-4">
{t('features:sustainability.how_it_works.title', 'Cómo funciona:')}
{t('sustainability.how_it_works.title', 'Cómo funciona:')}
</h3>
<ul className="space-y-3">
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-green-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:sustainability.how_it_works.item1', 'Bakery-IA genera reportes automáticos')}</span>
<span className="text-[var(--text-secondary)]">{t('sustainability.how_it_works.item1', 'Bakery-IA genera reportes automáticos')}</span>
</li>
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-green-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:sustainability.how_it_works.item2', 'Métricas de reducción de desperdicio (kg CO₂, litros agua)')}</span>
<span className="text-[var(--text-secondary)]">{t('sustainability.how_it_works.item2', 'Métricas de reducción de desperdicio (kg CO₂, litros agua)')}</span>
</li>
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-green-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:sustainability.how_it_works.item3', 'Documentación lista para solicitudes')}</span>
<span className="text-[var(--text-secondary)]">{t('sustainability.how_it_works.item3', 'Documentación lista para solicitudes')}</span>
</li>
<li className="flex items-start gap-3">
<CheckCircle2 className="w-5 h-5 text-green-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:sustainability.how_it_works.item4', 'Te ayudamos con el proceso')}</span>
<span className="text-[var(--text-secondary)]">{t('sustainability.how_it_works.item4', 'Te ayudamos con el proceso')}</span>
</li>
</ul>
</div>
@@ -796,17 +796,17 @@ const FeaturesPage: React.FC = () => {
<div className="bg-gradient-to-br from-green-50 to-emerald-50 dark:from-green-900/20 dark:to-emerald-900/20 rounded-xl p-6 border border-green-200 dark:border-green-800 text-center">
<TreeDeciduous className="w-12 h-12 text-green-600 mx-auto mb-3" />
<div className="text-3xl font-bold text-green-700 dark:text-green-400 mb-2">85kg CO</div>
<p className="text-sm text-[var(--text-secondary)]">{t('features:sustainability.impact.co2', 'reducidos al mes (equivale a 3 árboles plantados)')}</p>
<p className="text-sm text-[var(--text-secondary)]">{t('sustainability.impact.co2', 'reducidos al mes (equivale a 3 árboles plantados)')}</p>
</div>
<div className="bg-gradient-to-br from-blue-50 to-cyan-50 dark:from-blue-900/20 dark:to-cyan-900/20 rounded-xl p-6 border border-blue-200 dark:border-blue-800 text-center">
<Droplets className="w-12 h-12 text-blue-600 mx-auto mb-3" />
<div className="text-3xl font-bold text-blue-700 dark:text-blue-400 mb-2">675,000L</div>
<p className="text-sm text-[var(--text-secondary)]">{t('features:sustainability.impact.water', 'agua ahorrada al año')}</p>
<p className="text-sm text-[var(--text-secondary)]">{t('sustainability.impact.water', 'agua ahorrada al año')}</p>
</div>
<div className="bg-gradient-to-br from-amber-50 to-orange-50 dark:from-amber-900/20 dark:to-orange-900/20 rounded-xl p-6 border border-amber-200 dark:border-amber-800 text-center">
<Award className="w-12 h-12 text-amber-600 mx-auto mb-3" />
<div className="text-3xl font-bold text-amber-700 dark:text-amber-400 mb-2">{t('features:sustainability.impact.certification', 'Certificado')}</div>
<p className="text-sm text-[var(--text-secondary)]">{t('features:sustainability.impact.certification_desc', 'ODS 12.3 ONU')}</p>
<div className="text-3xl font-bold text-amber-700 dark:text-amber-400 mb-2">{t('sustainability.impact.certification', 'Certificado')}</div>
<p className="text-sm text-[var(--text-secondary)]">{t('sustainability.impact.certification_desc', 'ODS 12.3 ONU')}</p>
</div>
</div>
</div>
@@ -817,10 +817,10 @@ const FeaturesPage: React.FC = () => {
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-3xl lg:text-4xl font-extrabold text-[var(--text-primary)] mb-4">
{t('features:business_models.title', 'Para Cualquier Modelo de Negocio')}
{t('business_models.title', 'Para Cualquier Modelo de Negocio')}
</h2>
<p className="text-xl text-[var(--text-secondary)]">
{t('features:business_models.subtitle', 'No importa cómo trabajes, funciona para ti')}
{t('business_models.subtitle', 'No importa cómo trabajes, funciona para ti')}
</p>
</div>
@@ -830,19 +830,19 @@ const FeaturesPage: React.FC = () => {
<Store className="w-6 h-6 text-[var(--color-primary)]" />
</div>
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-4">
{t('features:business_models.local.title', 'Panadería Producción Local')}
{t('business_models.local.title', 'Panadería Producción Local')}
</h3>
<p className="text-[var(--text-secondary)] mb-4">
{t('features:business_models.local.description', 'Horneas y vendes en el mismo local')}
{t('business_models.local.description', 'Horneas y vendes en el mismo local')}
</p>
<ul className="space-y-2">
<li className="flex items-start gap-2">
<CheckCircle2 className="w-5 h-5 text-[var(--color-primary)] mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:business_models.local.benefit1', 'IA optimiza producción diaria')}</span>
<span className="text-[var(--text-secondary)]">{t('business_models.local.benefit1', 'IA optimiza producción diaria')}</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-5 h-5 text-[var(--color-primary)] mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:business_models.local.benefit2', 'Gestiona inventario de un punto')}</span>
<span className="text-[var(--text-secondary)]">{t('business_models.local.benefit2', 'Gestiona inventario de un punto')}</span>
</li>
</ul>
</div>
@@ -852,23 +852,23 @@ const FeaturesPage: React.FC = () => {
<Globe className="w-6 h-6 text-blue-600" />
</div>
<h3 className="text-xl font-bold text-[var(--text-primary)] mb-4">
{t('features:business_models.central.title', 'Obrador Central + Puntos de Venta')}
{t('business_models.central.title', 'Obrador Central + Puntos de Venta')}
</h3>
<p className="text-[var(--text-secondary)] mb-4">
{t('features:business_models.central.description', 'Produces en obrador, distribuyes a tiendas')}
{t('business_models.central.description', 'Produces en obrador, distribuyes a tiendas')}
</p>
<ul className="space-y-2">
<li className="flex items-start gap-2">
<CheckCircle2 className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:business_models.central.benefit1', 'IA predice demanda por punto de venta')}</span>
<span className="text-[var(--text-secondary)]">{t('business_models.central.benefit1', 'IA predice demanda por punto de venta')}</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:business_models.central.benefit2', 'Optimiza distribución y transporte')}</span>
<span className="text-[var(--text-secondary)]">{t('business_models.central.benefit2', 'Optimiza distribución y transporte')}</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0" />
<span className="text-[var(--text-secondary)]">{t('features:business_models.central.benefit3', 'Gestiona inventario central + puntos')}</span>
<span className="text-[var(--text-secondary)]">{t('business_models.central.benefit3', 'Gestiona inventario central + puntos')}</span>
</li>
</ul>
</div>
@@ -880,17 +880,17 @@ const FeaturesPage: React.FC = () => {
<section className="py-20 bg-gradient-to-r from-[var(--color-primary)] to-orange-600">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 className="text-3xl lg:text-4xl font-bold text-white mb-6">
{t('features:cta.title', 'Ver Bakery-IA en Acción')}
{t('cta.title', 'Ver Bakery-IA en Acción')}
</h2>
<p className="text-xl text-white/90 mb-8">
{t('features:cta.subtitle', 'Solicita una demo personalizada para tu panadería')}
{t('cta.subtitle', 'Solicita una demo personalizada para tu panadería')}
</p>
<Link to={getDemoUrl()}>
<Button
size="lg"
className="bg-white text-[var(--color-primary)] hover:bg-gray-100 font-bold text-lg px-8 py-4"
>
{t('features:cta.button', 'Solicitar Demo')}
{t('cta.button', 'Solicitar Demo')}
<ArrowRight className="ml-2 w-5 h-5" />
</Button>
</Link>

View File

@@ -2,6 +2,13 @@
* Component styles for reusable UI components
*/
/* Fix for no-underline utility - override global a:hover rule */
.no-underline,
.no-underline:hover,
.no-underline:focus {
text-decoration: none !important;
}
/* Custom Utility Classes for CSS Variables */
/* Background Color Utilities */