# Guía para Adaptar un Nuevo Demo de Porto al Sistema CMS

## 🚀 INSTRUCCIONES DE USO

**Cuando el usuario especifique un demo (ej: "demo-restaurant"), debes:**

1. **Reemplazar `{demo-name}`** en todo este documento con el nombre real del demo (ej: `restaurant` → todas las referencias serán `demo-restaurant`)
2. **VERIFICAR RUTAS DISPONIBLES** antes de crear los archivos (ver sección "Verificación de Rutas" abajo)
3. **Leer los archivos HTML de Porto** especificados para extraer el código
4. **Seguir TODOS los pasos** del checklist sin omitir ninguno
5. **Crear/modificar TODOS los archivos** listados
6. **Verificar** que todo funcione correctamente

**Formato de entrada del usuario:**
- "Adapta el demo-restaurant"
- "Quiero migrar demo-restaurant"
- "demo-restaurant"

---

## 🔍 VERIFICACIÓN DE RUTAS (PASO PREVIO OBLIGATORIO)

**ANTES de crear cualquier archivo, debes verificar qué rutas están disponibles en el sistema:**

**Comando para listar rutas:**
```bash
php artisan route:list | grep "front\."
```

**O buscar directamente en archivos de rutas:**
```bash
grep -r "name('front\." routes/modules/cd-base.php
grep -r "->name('about')" routes/modules/cd-base.php
grep -r "->name('contact')" routes/modules/cd-base.php
```

**Rutas comunes del sistema (verificar en `routes/modules/cd-base.php`):**
- `front.homepage` o `front.welcome` - Página principal
- `front.about` - Página about
- `front.contact` - Página contact  
- `front.contact.store` - POST del formulario de contacto
- `front.newsletter.subscribe` - Newsletter (verificar que existe)

**Rutas de búsqueda:**
- `search` - Búsqueda genérica (definida en `routes/web.php`)
- `frontend.news.search` - Búsqueda de noticias (si el módulo news está activo)
- **⚠️ NO existe `frontend.search`** - Usar `route('search') ?? url('/search')` en su lugar

**Rutas de módulos (IMPORTANTE - verificar si el módulo está activo):**

| Módulo | Ruta Index | Ruta Detalle | Ruta Categoría |
|--------|-----------|-------------|----------------|
| Blog | `blog.index` | `blog.post` (param: `$slug`) | `blog.category` (param: `$slug`) |
| Services | `frontend.services.index` | `frontend.services.detail` (param: `$slug`) | — |
| Products | `front.products.index` | `front.products.show` (param: `$slug`) | `front.products.category` (param: `$slug`) |
| Projects | `frontend.projects.index` | `frontend.projects.show` (param: `$slug`) | `frontend.projects.category` (param: `$slug`) |
| Gallery | `frontend.gallery.index` | — | `frontend.gallery.gallery.category` (param: `$slug`) |
| Team | `frontend.team.index` | `frontend.team.profile` (param: `$slug`) | — |
| News | `frontend.news.index` | `frontend.news.show` (param: `$slug`) | `frontend.news.category` (param: `$slug`) |
| References | `frontend.references.index` | — | `frontend.references.category` (param: `$slug`) |
| Menu | `front.menu.index` | `front.menu.show` (param: `$slug`) | `front.menu.category` (param: `$slug`) |
| FAQs | `faqs.index` | — | — |

**⚠️ NOMBRES QUE NO EXISTEN (errores comunes):**
- `frontend.services.show` → **CORRECTO:** `frontend.services.detail`
- `blog.show` → **CORRECTO:** `blog.post`
- `frontend.blog.index` → **CORRECTO:** `blog.index`
- `frontend.search` → **CORRECTO:** `search`
- `frontend.about` → **CORRECTO:** `front.about`
- `frontend.contact` → **CORRECTO:** `front.contact`

- **REGLA CRÍTICA:** SIEMPRE verificar si el módulo está activo antes de usar la ruta:
  ```blade
  @if(is_module_active('blog'))
      <a href="{{ route('blog.index') }}">Blog</a>
  @endif
  ```

**Si una ruta NO existe:**
- Usar `url('/ruta')` en lugar de `route('nombre.ruta')`
- O usar `{{ route('nombre.ruta') ?? url('/ruta') }}` como fallback
- O simplemente usar `url('/')` para homepage, `url('/about')` para about, etc.

**Ejemplo de uso seguro:**
```blade
{{-- SIEMPRE usar fallback para evitar RouteNotFoundException --}}
<a href="{{ route('front.about') ?? url('/about') }}">About</a>

{{-- Para rutas de módulos, verificar módulo activo primero --}}
@if(is_module_active('blog'))
    <a href="{{ route('blog.index') }}">Blog</a>
@endif

{{-- Para formularios de búsqueda --}}
<form action="{{ route('search') ?? url('/search') ?? '#' }}" method="get">
    <input name="q" type="search">
</form>

{{-- Si no estás seguro, usar directamente url() --}}
<a href="{{ url('/about') }}">About</a>
```

**⚠️ REGLA DE ORO:** NUNCA usar `route('nombre.ruta')` sin fallback. SIEMPRE: `{{ route('nombre.ruta') ?? url('/ruta') ?? '#' }}`

**⚠️ RUTAS QUE NO EXISTEN (evitar):**
- `frontend.search` - NO existe, usar `route('search')` en su lugar
- `frontend.about` - NO existe, usar `route('front.about')` en su lugar
- `frontend.contact` - NO existe, usar `route('front.contact')` en su lugar
- `frontend.blog.index` - NO existe, usar `route('blog.index')` con verificación de módulo activo

**⚠️ RUTAS DE MÓDULOS - PATRÓN CORRECTO:**
```blade
{{-- ✅ CORRECTO: Verificar módulo activo primero --}}
@if(is_module_active('blog'))
    <a href="{{ route('blog.index') }}">Blog</a>
@endif

{{-- ❌ INCORRECTO: Usar ruta sin verificar o ruta incorrecta --}}
<a href="{{ route('frontend.blog.index') }}">Blog</a>
{{-- ❌ INCORRECTO: Usar ruta sin verificar módulo activo --}}
<a href="{{ route('blog.index') }}">Blog</a>
```

---

## 📋 ESPECIFICACIÓN DEL DEMO

**Nombre del Demo:** `{demo-name}` (será reemplazado por el nombre real, ej: `demo-restaurant`)

**Archivos HTML de Porto a leer:**
- `demo-{demo-name}.html` - Página principal (welcome)
- `demo-{demo-name}-about.html` - Página About (si existe)
- `demo-{demo-name}-contact.html` - Página Contact (si existe)

**Archivos CSS de Porto a copiar:**
- `css/demos/demo-{demo-name}.css` → `public/template/css/demos/demo-{demo-name}.css`
- `css/skins/skin-{demo-name}.css` → `public/template/css/skins/skin-{demo-name}.css`

**Carpeta de imágenes a copiar:**
- `img/demos/{demo-name}/` → `public/cd-project/img/demos/{demo-name}/` (estructura completa)

---

## ✅ TAREAS A REALIZAR (en orden)

### TAREA 0: Configuración del Sistema (ANTES de crear vistas)

**ACCIÓN:** Configurar el sistema para que reconozca el nuevo demo antes de crear cualquier archivo de vista.

**0.1 - Configurar Google Fonts del demo:**
1. Abrir el HTML de Porto del demo y buscar la línea `<link id="googleFonts" ...>`
2. Extraer las familias de fuentes (ej: `Playfair+Display:400,700|Sintony:400,700`)
3. Actualizar `database/seeders/project-data/cd-system.json` agregando las fuentes:
```json
{
  "theme": {
    "demo": "demo-{demo-name}",
    "skin": "auto",
    "fonts": {
      "primary": "NombreFuenteHeadings",
      "secondary": "NombreFuenteBody",
      "tertiary": "Open Sans"
    }
  }
}
```
**⚠️ CRÍTICO:** Si no se configuran las fuentes, el sistema cargará las fuentes por defecto (Lexend) y el demo se verá completamente distinto al original de Porto.

**0.2 - Verificar mappings en `app/helpers.php`:**
- Verificar que `demo-{demo-name}` existe en `get_demo_skin_mapping()` (generalmente ya viene pre-configurado)
- Verificar que `demo-{demo-name}` existe en `get_demo_layout_mapping()`. Si no existe, agregar:
```php
'demo-{demo-name}' => [
    'header' => 'demo-{demo-name}',
    'footer' => 'demo-{demo-name}',
    'sidebar' => 'default',
    'description' => 'Template para {descripción}',
    'features' => ['...'],
],
```

**0.3 - Registrar en `config/page-headers.php`:**
```php
'demo-{demo-name}' => [
    'default_type' => 'classic', // o 'modern' según el estilo del demo
    'modules' => [
        'services' => 'classic',
        'products' => 'classic',
        'blog' => 'classic',
        'faqs' => 'classic',
        'references' => 'classic',
        'team-members' => 'classic',
        'gallery' => 'classic',
        'projects' => 'classic',
    ],
],
```

**0.4 - Ejecutar seeders y limpiar caché:**
```bash
php artisan db:seed --class=CdSystemSeeder
php artisan db:seed --class=SiteDataSeeder
php artisan config:clear && php artisan cache:clear && php artisan view:clear
```

**Verificar:** `config('cd-system.theme.demo')` retorna `demo-{demo-name}` y las fuentes de Google Fonts se cargan correctamente.

---

### TAREA 1: Copiar archivos CSS y assets

**ACCIÓN:** Copiar los archivos CSS y la carpeta de imágenes desde Porto al sistema.

1. Copiar `css/demos/demo-{demo-name}.css` → `public/template/css/demos/demo-{demo-name}.css`
2. Copiar `css/skins/skin-{demo-name}.css` → `public/template/css/skins/skin-{demo-name}.css`
3. Copiar toda la carpeta `img/demos/{demo-name}/` → `public/cd-project/img/demos/{demo-name}/` (mantener estructura de subcarpetas: backgrounds/, generic/, icons/, blog/, etc.)

**⚠️ IMPORTANTE - Clases base de iconos:**
Si el demo usa iconos de simple-line-icons con formato `icon icon-clock` o `icons icon-magnifier`, verificar que las clases base `.icon` y `.icons` estén definidas en `public/template/css/custom.css`. Si no están, agregarlas:

```css
/* Clases base para Porto 13.0.0 */
i.icon,
i.icons,
.icon,
.icons,
i[class*="icon-"],
[class*="icon-"] {
	font-family: 'simple-line-icons' !important;
	speak: none;
	font-style: normal;
	font-weight: normal;
	font-variant: normal;
	text-transform: none;
	line-height: 1;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

/* Asegurar que funcionen cuando se combinan clases */
.icon.icon-clock,
.icons.icon-magnifier,
.icon[class*="icon-"],
.icons[class*="icon-"],
i.icon[class*="icon-"],
i.icons[class*="icon-"] {
	font-family: 'simple-line-icons' !important;
}

/* Asegurar que :before funcione correctamente */
.icon.icon-clock:before,
.icons.icon-magnifier:before,
.icon[class*="icon-"]:before,
.icons[class*="icon-"]:before {
	font-family: 'simple-line-icons' !important;
}
```

**⚠️ IMPORTANTE:** Después de agregar estas clases, limpiar caché del navegador (Ctrl+F5 / Cmd+Shift+R) y caché de Laravel:
```bash
php artisan view:clear
php artisan config:clear
php artisan cache:clear
```

**Verificar:** 
- Los archivos CSS existen en las ubicaciones correctas
- La carpeta de imágenes se copió completamente con todas sus subcarpetas
- Todas las imágenes referenciadas en los blades existen físicamente en el sistema
- Las clases base `.icon` y `.icons` están definidas en `custom.css` (requerido para Porto 13.0.0)
- Usar `ls -R public/cd-project/img/demos/{demo-name}/` para verificar estructura completa

---

### TAREA 2: Crear Header del Demo

**ARCHIVO A CREAR:** `resources/views/layout/front/headers/{demo-name}.blade.php`

**ACCIÓN:**
1. Leer el archivo HTML de Porto (`demo-{demo-name}.html`)
2. Extraer TODO el contenido dentro de `<header id="header" ...>...</header>`
3. Adaptar el código:
   - Reemplazar logo: `src="img/demos/{demo-name}/logo.png"` → `{{ asset(config('site.assets.main_logo')) }}`
   - Adaptar navegación usando `get_dynamic_navigation('header')` o mantener estructura original si es muy específica
   - Adaptar teléfono/horarios usando `config('site.contact.phone')` y configuración del sistema
   - Mantener TODAS las clases CSS, atributos `data-plugin-options`, y estructura HTML exacta
   - Adaptar iconos de redes sociales usando `config('site.social_media')`
   - Convertir todas las imágenes a `{{ asset('cd-project/img/demos/{demo-name}/...') }}`
   - **TODAS las rutas DEBEN tener fallback:** `{{ route('nombre.ruta') ?? url('/ruta') }}`
   - **Formularios de búsqueda:** `action="{{ route('search') ?? url('/search') }}"` (NO usar `frontend.search`)

**Estructura base:**
```blade
<header id="header" class="header-effect-shrink @yield('header_classes')" data-plugin-options="...">
    <div class="header-body">
        {{-- Header top si existe --}}
        {{-- Header container con logo y navegación --}}
    </div>
</header>
```

**Verificar:** El header se muestra correctamente con todas sus funcionalidades.

---

### TAREA 3: Crear Footer del Demo

**ARCHIVO A CREAR:** `resources/views/layout/front/footers/{demo-name}.blade.php`

**ACCIÓN:**
1. Leer el archivo HTML de Porto
2. Extraer TODO el contenido dentro de `<footer id="footer" ...>...</footer>`
3. Adaptar el código:
   - Reemplazar logo: usar `{{ asset(config('site.assets.footer_logo')) }}`
   - Adaptar información de contacto: `config('site.contact.phone')`, `config('site.contact.email')`, `config('site.contact.address.*')`
   - Adaptar enlaces de navegación usando configuración del sistema
   - Integrar formulario de newsletter si existe: usar `{{ route('front.newsletter.subscribe') ?? url('/newsletter') }}` y `@csrf`
   - Mantener Google Maps si aplica (preservar configuración de API)
   - Adaptar redes sociales usando `config('site.social_media')`
   - Convertir todas las imágenes a `{{ asset('cd-project/img/demos/{demo-name}/...') }}`
   - Mantener estructura y clases CSS exactas
   - **TODAS las rutas DEBEN tener fallback:** `{{ route('nombre.ruta') ?? url('/ruta') }}`
   - **Rutas de módulos:** SIEMPRE verificar con `@if(is_module_active('modulo'))` antes de usar la ruta
   - **Blog:** Usar `route('blog.index')` con `@if(is_module_active('blog'))`, NO usar `frontend.blog.index`

**Verificar:** El footer se muestra correctamente con todas sus secciones.

---

### TAREA 4: Crear welcome.blade.php (ENFOQUE ESTÁTICO-PRIMERO)

**ARCHIVO A CREAR:** `resources/views/modules/cd-base/frontend/demos/{demo-name}/welcome.blade.php`

**⚠️ REGLA FUNDAMENTAL - DOS FASES:**

**FASE 1 (esta tarea): Copia estática idéntica al HTML de Porto.**
El welcome.blade.php debe ser una réplica EXACTA del HTML de Porto. NO agregar contenido dinámico (`is_module_active`, `$services`, `config('site.*')`, `__()`, etc.) en esta fase. Solo adaptar lo mínimo indispensable para que funcione en Blade.

**FASE 2 (posterior, cuando el usuario lo solicite): Dinamización.**
Una vez que el demo se ve idéntico al original de Porto, se procede a reemplazar contenido estático por datos dinámicos del CMS.

**ACCIÓN (FASE 1):**
1. Leer `demo-{demo-name}.html`
2. Extraer TODO el contenido dentro de `<div role="main" class="main">...</div>`
3. Copiar el HTML EXACTO, solo adaptando:

**Lo ÚNICO que se adapta en Fase 1:**
- ✅ `src="img/demos/{demo-name}/..."` → `{{ asset('cd-project/img/demos/{demo-name}/...') }}`
- ✅ `style="background-image: url(img/..."` → `style="background-image: url({{ asset('cd-project/img/...') }})"`
- ✅ `action="php/contact-form.php"` → `action="{{ route('front.contact.store') ?? url('/contact') }}"` + agregar `@csrf`
- ✅ Agregar `{{ old('name') }}` etc. en campos de formulario para repoblación
- ✅ Agregar `@if(session('success'))` y `@if($errors->any())` para mensajes del formulario
- ✅ Links internos (`href="demo-{demo-name}-about.html"`) → `href="{{ route('front.about') ?? url('/about') }}"`
- ✅ Wrap con `@extends('layout.front.master')`, `@section('content')`, `@endsection`
- ✅ Meta tags SEO estándar (ver estructura abajo)

**Lo que NO se modifica en Fase 1 (se deja como texto estático de Porto):**
- ❌ NO usar `{{ __('texto') }}` para traducciones - dejar el texto original en inglés
- ❌ NO usar `config('site.contact.phone')` - dejar el teléfono de ejemplo de Porto
- ❌ NO usar `is_module_active()` - todas las secciones se muestran siempre
- ❌ NO usar `$services`, `$featuredProducts`, `$recentPosts` etc. - dejar contenido estático
- ❌ NO usar `config('site.description')` - dejar el "Lorem ipsum" de Porto
- ❌ NO iterar con `@foreach` sobre datos de módulos

**Estructura base:**
```blade
@extends('layout.front.master')

@section('title', __('Inicio'))
@section('description', config('site.seo.description'))
@section('keywords', config('site.seo.keywords'))

@section('og_title', config('site.og.title'))
@section('og_description', config('site.og.description'))
@section('og_image', asset(config('site.og.image')))
@section('og_type', 'website')
@section('og_url', url()->current())

@section('twitter_title', config('site.name'))
@section('twitter_description', config('site.twitter.description'))
@section('twitter_image', asset('cd-project/img/meta-tags/twitter-image.png'))

@section('content')

{{-- COPIA EXACTA del contenido de <div role="main"> del HTML de Porto --}}
{{-- Solo adaptar: rutas de imágenes con asset(), links internos con route(), y formulario con @csrf --}}

@endsection
```

**Verificar:** Abrir la página en el navegador y compararla visualmente con el demo original de Porto. Deben ser IDÉNTICAS.

**Referencia del demo original:** `https://www.okler.net/previews/porto/13.0.0/demo-{demo-name}.html`

---

### TAREA 5: Crear about.blade.php

**ARCHIVO A CREAR:** `resources/views/modules/cd-base/frontend/demos/{demo-name}/about.blade.php`

**ACCIÓN:**
1. Leer `demo-{demo-name}-about.html` o extraer sección "About Us" del HTML principal
2. Crear el archivo con esta estructura:

```blade
@extends('layout.front.master')

@section('title', __('Empresa'))
@section('description', config('site.seo.description'))
@section('keywords', config('site.seo.keywords'))

@section('content')

@include('modules.cd-base.frontend.partials.dynamic-header', [
    'pageTitle' => __('Nuestra Empresa'),
    'breadcrumbItems' => [
        ['url' => url('/'), 'label' => __('Inicio')],
        ['url' => null, 'label' => __('Empresa')]
    ]
])

{{-- Extraer contenido principal del HTML original --}}
{{-- Aplicar mismas adaptaciones que welcome.blade.php --}}

@endsection
```

**Adaptaciones:** Mismas que welcome.blade.php

**⚠️ IMPORTANTE:** Verificar rutas disponibles antes de usar (ver sección de welcome.blade.php)

**Verificar:** La página about carga y muestra el dynamic-header correcto.

---

### TAREA 6: Crear contact.blade.php

**ARCHIVO A CREAR:** `resources/views/modules/cd-base/frontend/demos/{demo-name}/contact.blade.php`

**ACCIÓN:**
1. Leer `demo-{demo-name}-contact.html` o extraer sección de contacto
2. Crear el archivo con esta estructura:

```blade
@extends('layout.front.master')

@section('title', __('Contacto'))
@section('description', config('site.seo.description'))
@section('keywords', config('site.seo.keywords'))

@section('content')

@include('modules.cd-base.frontend.partials.dynamic-header', [
    'pageTitle' => __('Contáctanos'),
    'breadcrumbItems' => [
        ['url' => url('/'), 'label' => __('Inicio')],
        ['url' => null, 'label' => __('Contacto')]
    ]
])

{{-- FORMULARIO DE CONTACTO --}}
<form id="contactForm" action="{{ route('front.contact.store') }}" method="POST">
    @csrf
    {{-- Extraer campos del formulario original --}}
    {{-- Adaptar para usar Laravel --}}
</form>

{{-- INFORMACIÓN DE CONTACTO --}}
{{-- Usar config('site.contact.*') --}}

@endsection

@section('scripts')
<script>
    {{-- Código JS del formulario adaptado para Laravel --}}
</script>
@endsection
```

**Adaptaciones obligatorias:**
- ✅ Formulario: `action="{{ route('front.contact.store') ?? url('/contact') }}"` y `@csrf` (SIEMPRE usar fallback)
- ✅ Campos con `name` y `id` apropiados
- ✅ Información de contacto: `config('site.contact.phone')`, `config('site.contact.email')`, etc.
- ✅ Mismas adaptaciones de rutas e imágenes que welcome.blade.php

**⚠️ IMPORTANTE:** Si `route('front.contact.store')` no existe, el fallback `url('/contact')` funcionará igual (el método POST se mantiene)

**Verificar:** El formulario funciona y envía correctamente.

---

### TAREA 7: Actualizar Dynamic Headers

**ARCHIVOS A MODIFICAR (10 archivos - NO omitir ninguno):**
1. `resources/views/modules/cd-base/frontend/partials/dynamic-header.blade.php`
2. `resources/views/modules/blog/frontend/partials/dynamic-header.blade.php`
3. `resources/views/modules/products/frontend/partials/dynamic-header.blade.php`
4. `resources/views/modules/services/frontend/partials/dynamic-header.blade.php`
5. `resources/views/modules/projects/frontend/partials/dynamic-header.blade.php`
6. `resources/views/modules/gallery/frontend/partials/dynamic-header.blade.php`
7. `resources/views/modules/references/frontend/partials/dynamic-header.blade.php`
8. `resources/views/modules/team-members/frontend/partials/dynamic-header.blade.php`
9. `resources/views/modules/menu/frontend/partials/dynamic-header.blade.php`
10. `resources/views/modules/cd-base/faqs/frontend/partials/dynamic-header.blade.php`

**ACCIÓN para cada archivo:**

1. **Identificar el estilo del page-header:**
   - Revisar las páginas about y contact del HTML de Porto
   - Extraer el código del page-header (generalmente `<section class="page-header ...">`)

2. **Agregar al inicio del bloque PHP:**
   ```php
   $isDemoName = ($activeDemo === 'demo-{demo-name}');
   ```

3. **Agregar el bloque del estilo:**
   ```blade
   @elseif($isDemoName)
       {{-- Estilo específico del demo extraído del HTML de Porto --}}
       <section class="page-header ...">
           {{-- Breadcrumbs y título usando variables $pageTitle, $breadcrumbItems, $pageSubtitle --}}
       </section>
   ```

**Ejemplo completo a agregar:**
```blade
@php
    $activeDemo = get_active_demo();
    $isDemoName = ($activeDemo === 'demo-{demo-name}');
    // ... otras variables existentes
@endphp

@if($isLawFirm2)
    {{-- Estilos existentes --}}
@elseif($isDemoName)
    {{-- ESTILO ESPECÍFICO DEL NUEVO DEMO --}}
    <section class="page-header page-header-modern page-header-lg overlay overlay-show overlay-op-9 m-0" 
             style="background-image: url({{ $backgroundImage ?? asset('cd-project/img/demos/{demo-name}/backgrounds/background-1.jpg') }}); background-size: cover; background-position: center;">
        <div class="container py-4">
            <div class="row">
                <div class="col text-center">
                    <ul class="breadcrumb d-flex justify-content-center text-4-5 font-weight-medium mb-2">
                        @foreach($breadcrumbItems as $index => $item)
                            @if($index === count($breadcrumbItems) - 1)
                                <li class="text-color-primary active">{{ strtoupper($item['label']) }}</li>
                            @else
                                <li>
                                    <a href="{{ $item['url'] }}" class="text-color-primary text-decoration-none">{{ strtoupper($item['label']) }}</a>
                                </li>
                            @endif
                        @endforeach
                    </ul>
                    <h1 class="text-color-light font-weight-bold text-10">{{ $pageTitle }}</h1>
                    @if(!empty($pageSubtitle))
                        <p class="text-color-light opacity-7 mt-2">{{ $pageSubtitle }}</p>
                    @endif
                </div>
            </div>
        </div>
    </section>
@elseif($isDigitalAgency2)
    {{-- Otros estilos existentes --}}
@endif
```

**Verificar:** Los dynamic-headers funcionan en todos los módulos.

---

## ✅ CHECKLIST FINAL DE VERIFICACIÓN

Antes de considerar la migración completa, verificar:

**Configuración del sistema (TAREA 0):**
- [ ] Google Fonts configuradas en `cd-system.json` → `theme.fonts` (verificar que coinciden con las del HTML de Porto)
- [ ] Demo registrado en `get_demo_layout_mapping()` de `app/helpers.php`
- [ ] Skin mapping verificado en `get_demo_skin_mapping()` de `app/helpers.php`
- [ ] Demo registrado en `config/page-headers.php` con tipo correcto para cada módulo
- [ ] Seeders ejecutados (`CdSystemSeeder` + `SiteDataSeeder`)
- [ ] Caché limpiada (`config:clear`, `cache:clear`, `view:clear`)

**Assets (TAREA 1):**
- [ ] Archivos CSS copiados: `demos/demo-{demo-name}.css` y `skins/skin-{demo-name}.css`
- [ ] Carpeta de imágenes copiada completamente a `public/cd-project/img/demos/{demo-name}/`
- [ ] Clases base de iconos (`.icon` y `.icons`) están definidas en `custom.css`

**Vistas (TAREAS 2-6):**
- [ ] Header creado y funcionando (`layout/front/headers/demo-{demo-name}.blade.php`)
- [ ] Footer creado y funcionando (`layout/front/footers/demo-{demo-name}.blade.php`)
- [ ] welcome.blade.php es una copia estática IDÉNTICA al HTML de Porto (Fase 1)
- [ ] about.blade.php creado y dynamic-header funciona
- [ ] contact.blade.php creado y formulario funciona con `@csrf`

**Dynamic Headers (TAREA 7):**
- [ ] Dynamic-header actualizado en TODOS los módulos (**10 archivos**, incluyendo menu y faqs)

**Verificación visual:**
- [ ] Comparar visualmente welcome con el demo original de Porto - deben ser IDÉNTICAS
- [ ] Verificar que NO hay errores de `RouteNotFoundException`
- [ ] TODAS las imágenes cargan (no hay 404)
- [ ] Google Fonts se cargan (verificar en Network tab del navegador: Playfair, Sintony, etc.)
- [ ] Iconos se muestran correctamente (no cuadrados)
- [ ] No hay errores en la consola del navegador
- [ ] Responsive funciona en móvil, tablet y desktop
- [ ] Animaciones y carousels funcionan correctamente

---

## 📚 REFERENCIAS

Para ver ejemplos de demos ya adaptados:
- `demo-accounting-1` - Ejemplo básico completo
- `demo-construction` - Ejemplo con dynamic-header personalizado
- `demo-transportation-logistic` - Ejemplo con estructura compleja

**Ubicaciones:**
- Blades: `resources/views/modules/cd-base/frontend/demos/{demo-name}/`
- Headers: `resources/views/layout/front/headers/{demo-name}.blade.php`
- Footers: `resources/views/layout/front/footers/{demo-name}.blade.php`

---

## ⚠️ REGLAS IMPORTANTES

1. **ESTÁTICO PRIMERO:** La primera versión del welcome.blade.php debe ser una copia EXACTA del HTML de Porto. Solo adaptar imágenes (`asset()`), links internos (`route()`), y formularios (`@csrf`). NO dinamizar con `config()`, `is_module_active()`, `$variables`, o `__()` hasta que el demo se vea idéntico al original.
2. **Preservar estructura original:** Mantener clases CSS y estructura HTML EXACTAMENTE como están en Porto. Si Porto tiene 9 items en un carousel, el blade debe tener 9 items.
3. **Google Fonts:** SIEMPRE verificar qué fuentes usa el demo de Porto (buscar `<link id="googleFonts" ...>` en el HTML) y configurarlas en `cd-system.json` → `theme.fonts`. Si no se configuran, el sistema cargará fuentes por defecto y el demo se verá distinto.
4. **Rutas absolutas:** TODAS las imágenes deben usar `{{ asset('...') }}`
5. **No modificar CSS:** Copiar archivos CSS sin cambios (excepto verificar clases base de iconos)
6. **Mantener plugins:** Preservar todos los atributos `data-plugin-options`
7. **Actualizar TODOS los dynamic-headers:** Son **10 archivos** (incluyendo menu y faqs). No omitir ninguno.
8. **VERIFICAR RUTAS:** Consultar la tabla de rutas de módulos en la sección "VERIFICACIÓN DE RUTAS". Los nombres de rutas NO son intuitivos (ej: `frontend.services.detail` NO `show`, `blog.post` NO `blog.show`).
9. **Rutas de módulos:** SIEMPRE verificar si el módulo está activo con `@if(is_module_active('modulo'))` antes de usar la ruta (aplica en Fase 2 de dinamización).
10. **Clases base de iconos (Porto 13.0.0):** Si el demo usa `icon icon-clock` o `icons icon-magnifier`, verificar que las clases base `.icon` y `.icons` estén en `custom.css`.
11. **Registrar el demo:** Además de crear las vistas, hay que registrar el demo en: `config/page-headers.php`, `get_demo_layout_mapping()`, y ejecutar los seeders.
12. **Orden CSS:** El CMS carga Demo CSS DESPUÉS de Skin y Custom CSS (distinto a Porto que carga Demo → Skin → Custom). Esto es intencional para que los estilos de marca del demo prevalezcan.
13. **Rutas comunes (usar con fallback):**
    - `{{ route('front.homepage') ?? route('front.welcome') ?? url('/') }}` - Página principal
    - `{{ route('front.about') ?? url('/about') }}` - Página about
    - `{{ route('front.contact') ?? url('/contact') }}` - Página contact
    - `{{ route('front.contact.store') ?? url('/contact') }}` - POST del formulario de contacto
    - `{{ route('front.newsletter.subscribe') ?? url('/newsletter') ?? '#' }}` - Newsletter
    - **Blog:** `@if(is_module_active('blog'))` + `{{ route('blog.index') }}` (NO usar `frontend.blog.index`)
    - `{{ route('search') ?? url('/search') }}` - Búsqueda genérica (NO usar `frontend.search`)

---

## 🛠️ COMANDOS DE VERIFICACIÓN

```bash
# Verificar archivos CSS
ls -lh public/template/css/demos/demo-{demo-name}.css
ls -lh public/template/css/skins/skin-{demo-name}.css

# Verificar imágenes
ls -R public/cd-project/img/demos/{demo-name}/

# Verificar Google Fonts cargadas (buscar en el HTML de Porto)
grep -i "googleFonts" /ruta/al/demo-{demo-name}.html

# Verificar rutas disponibles
php artisan route:list | grep "front\."
php artisan route:list | grep "about\|contact\|homepage"

# Buscar rutas en archivos de rutas
grep -r "name('front\." routes/
grep -r "->name('about')" routes/
grep -r "->name('contact')" routes/

# Verificar mappings en helpers.php
grep "demo-{demo-name}" app/helpers.php

# Verificar registro en page-headers.php
grep "demo-{demo-name}" config/page-headers.php

# Ejecutar seeders (OBLIGATORIO después de modificar cd-system.json o site-data.json)
php artisan db:seed --class=CdSystemSeeder
php artisan db:seed --class=SiteDataSeeder

# Limpiar caché
php artisan view:clear
php artisan config:clear
php artisan cache:clear

# Buscar rutas estáticas sin convertir
grep -r "href=\"demo-" resources/views/modules/cd-base/frontend/demos/{demo-name}/
grep -r "src=\"img/demos" resources/views/modules/cd-base/frontend/demos/{demo-name}/

# Verificar rutas usadas en los blades
grep -r "route(" resources/views/modules/cd-base/frontend/demos/{demo-name}/

# Verificar que todas las imágenes referenciadas existen
grep -roh "asset('cd-project/img/demos/{demo-name}/[^']*')" resources/views/modules/cd-base/frontend/demos/{demo-name}/ resources/views/layout/front/headers/{demo-name}.blade.php resources/views/layout/front/footers/{demo-name}.blade.php | sed "s/asset('cd-project\/img\/demos\/{demo-name}\///;s/')$//" | while read img; do [ -f "public/cd-project/img/demos/{demo-name}/$img" ] || echo "FALTA: $img"; done

# Verificar que los 10 dynamic-headers tienen la condición del nuevo demo
grep -l "demo-{demo-name}" resources/views/modules/*/frontend/partials/dynamic-header.blade.php resources/views/modules/cd-base/faqs/frontend/partials/dynamic-header.blade.php | wc -l
# Debe dar 10
```

---

## 🔄 FASE 2: DINAMIZACIÓN PARA UN PROYECTO (posterior)

**Esta fase se ejecuta DESPUÉS de que el demo se ve idéntico al original de Porto (Fase 1 completa).**

Cuando el usuario solicite "alinear al proyecto X" o "dinamizar el welcome", se procede a reemplazar contenido estático por datos del CMS:

**Pasos de dinamización del welcome.blade.php:**

1. **Textos estáticos → config/traducciones:**
   - `"Call Us Now"` → `{{ __('Call Us Now') }}`
   - `"+001 1230 4567"` → `{{ config('site.contact.phone') }}`
   - `"mail@example.com"` → `{{ config('site.contact.email') }}`
   - `"Lorem ipsum..."` → `{{ config('site.description', 'Lorem ipsum...') }}`

2. **Secciones de módulos → datos dinámicos:**
   - Envolver secciones con `@if(is_module_active('modulo'))` ... `@else` (fallback estático) ... `@endif`
   - Reemplazar items estáticos con `@foreach($services as $service)` etc.
   - Las variables (`$services`, `$featuredProducts`, `$recentPosts`, `$teamMembers`, `$featuredFaqs`) ya las provee `HomepageController::index()`

3. **Redes sociales → config dinámico:**
   ```blade
   @foreach(config('site.social_media', []) as $key => $social)
       @if($social['active'] ?? false)
           <li class="social-icons-{{ $key }}">
               <a href="{{ $social['url'] }}" target="_blank" title="{{ ucfirst($key) }}">
                   <i class="{{ $social['icon'] ?? 'fab fa-' . $key }}"></i>
               </a>
           </li>
       @endif
   @endforeach
   ```

4. **Header → navegación dinámica:**
   - Reemplazar `<ul>` estático por `get_dynamic_navigation('header')`
   - Ver header de `demo-insurance` como referencia

5. **Footer → datos del proyecto:**
   - Copyright: `{{ date('Y') }} © {{ config('site.name') }}`
   - Contacto: `config('site.contact.*')`

**⚠️ REGLA:** Al dinamizar, SIEMPRE mantener el fallback estático dentro de `@else` para que el demo funcione incluso sin datos en la DB.

---

## 🎯 RESUMEN DEL FLUJO COMPLETO

```
1. Usuario dice: "Adapta demo-{demo-name}"
   └── Se ejecutan TAREAS 0-7 (copia estática idéntica a Porto)
   └── Resultado: demo visible en el CMS, idéntico al original

2. Usuario dice: "Asigna este demo al proyecto X" 
   └── Se actualiza cd-system.json con demo, fonts, y módulos del proyecto
   └── Se ejecutan seeders
   └── Resultado: proyecto X usa el demo como su layout visual

3. Usuario dice: "Dinamiza el welcome para el proyecto"
   └── Se ejecuta FASE 2 (reemplazar estático por dinámico)
   └── Resultado: welcome muestra datos reales del proyecto
```

**Para que un demo ya montado sea seleccionable por otro proyecto:**
Solo se necesita cambiar en el `cd-system.json` del proyecto:
```json
{
  "theme": {
    "demo": "demo-{demo-name}",
    "skin": "auto",
    "fonts": { ... }
  }
}
```
Y ejecutar: `php artisan db:seed --class=CdSystemSeeder && php artisan config:clear && php artisan cache:clear`

---

**IMPORTANTE:** Al recibir el nombre del demo, reemplaza `{demo-name}` en todo el documento y ejecuta TODAS las tareas en orden, sin omitir ninguna.
