- eliminar carpetas vacias admin/herosection y bootstrapicons
- eliminar 7 scripts legacy con credenciales hardcodeadas
- eliminar formbuilder duplicado en shared/infrastructure/ui
- eliminar 11 archivos .gitkeep en carpetas con contenido
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Agrega propiedades flexbox al contenedor .hero-section para que el
contenido (título y badges) se muestre centrado verticalmente cuando
no hay badges de categorías.
Cambios:
- display: flex
- align-items: center
- justify-content: center
También incluye specs OpenSpec para arquitectura del tema.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Crear UserVisibilityHelper centralizado en Shared/Infrastructure/Services
- Añadir campo hide_for_logged_in en schemas de 4 componentes
- Integrar validación en Renderers: TopBar, LetsTalk, CTASidebar, CTAPost
- Añadir checkbox UI en FormBuilders de los 4 componentes
- Refactorizar adsense-placement.php para usar el helper centralizado
- Deprecar función roi_should_hide_for_logged_in() (backwards compatible)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Añadir PageVisibility use case y repositorio
- Implementar PageTypeDetector para detectar home/single/page/archive
- Actualizar FieldMappers con soporte show_on_[page_type]
- Extender FormBuilders con UI de visibilidad por página
- Refactorizar Renderers para evaluar visibilidad dinámica
- Limpiar schemas removiendo campos de visibilidad legacy
- Añadir MigrationCommand para migrar configuraciones existentes
- Implementar adsense-loader.js para carga lazy de ads
- Actualizar front-page.php con nueva estructura
- Extender DIContainer con nuevos servicios
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Revertir cambio a system fonts porque el parpadeo de iconos
(Bootstrap Icons) sigue presente, haciendo el cambio innecesario.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Eliminar @font-face de Poppins (critical-bootstrap.css, css-global-fonts.css)
- Actualizar --bs-body-font-family a system font stack
- Desactivar font preload en CriticalCSSInjector.php
- Actualizar bootstrap-subset.min.css
System fonts garantizan carga instantánea sin parpadeo.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove custom_css field from schema (v1.4.0 → v1.5.0)
- Remove buildCssGroup() from FormBuilder
- Remove renderCustomCSS() from Renderer
- Update layout: single JS card instead of 2-column layout
- Update descriptions to reference CustomCSSManager (TIPO 3)
CSS personalizado ahora se gestiona exclusivamente desde el
componente CustomCSSManager, eliminando duplicidad funcional.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
CSS injection is working correctly in production:
- roi-custom-deferred-css appears in page output
- 2 snippets with 24KB of CSS being injected
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Nuevo sistema de gestión de CSS personalizado con panel admin:
- Admin/CustomCSSManager: CRUD de snippets CSS (crítico/diferido)
- Public/CustomCSSManager: Inyección dinámica en frontend
- Schema JSON para configuración del componente
Migración de CSS estático a BD:
- Tablas APU (~14KB) → snippet diferido en BD
- Tablas Genéricas (~10KB) → snippet diferido en BD
- Comentadas funciones legacy en enqueue-scripts.php
Limpieza de archivos obsoletos:
- Eliminado build-bootstrap-subset.js
- Eliminado migrate-legacy-options.php
- Eliminado minify-css.php
- Eliminado purgecss.config.js
Beneficios:
- CSS editable desde admin sin tocar código
- Soporte crítico (head) y diferido (footer)
- Filtrado por scope (all/home/single/archive)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Agregar campo is_critical a schemas table-of-contents.json y cta-lets-talk.json
- Cambiar generateCSS() de private a public en TableOfContentsRenderer y CtaLetsTalkRenderer
- Registrar table-of-contents y cta-lets-talk en CRITICAL_RENDERERS
- Ahora 6 componentes inyectan CSS crítico inline en <head>
Componentes críticos:
- top-notification-bar
- navbar
- cta-lets-talk (NUEVO)
- hero
- featured-image
- table-of-contents (NUEVO)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- functions-addon.php: Validacion centralizada con wp_is_mobile()
Componentes con show_on_mobile=false NO se renderizan en mobile
Previene CLS de elementos ocultos con CSS
- FeaturedImageRenderer: Agrega aspect-ratio 16/9 para reservar espacio
Imagen usa object-fit:cover con position:absolute
Metodo generateCSS() ahora publico para CriticalCSSService
- CriticalCSSService: Agrega featured-image a CRITICAL_RENDERERS
CSS se inyecta en <head> antes de que cargue contenido
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Cuando el ScrollSpy detecta un nuevo heading activo,
el TOC sidebar ahora hace scroll automático para
mostrar el elemento activo usando scrollIntoView
con behavior: smooth y block: nearest.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Agrega outline: none para .toc-link:focus via CSSGenerator
para remover el borde azul del browser al hacer clic.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problema: Los headings no tenían atributo id porque el filtro
PHP the_content se agregaba después de procesar el contenido.
Solución: El script del TOC ahora:
1. Busca cada link del TOC
2. Encuentra el heading correspondiente por texto
3. Asigna el ID esperado al heading
4. Luego configura smooth scroll e IntersectionObserver
Esto resuelve:
- Links del TOC no clickeables
- Smooth scroll no funcionaba
- ScrollSpy no rastreaba secciones
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
El método getVisibilityClasses() existía pero no se usaba.
Ahora buildClasses() verifica show_on_desktop y show_on_mobile
para aplicar clases Bootstrap (d-none d-lg-block, d-lg-none, etc.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace scroll event listener with Intersection Observer in TableOfContentsRenderer
- Eliminates ~100ms forced reflows from offsetTop reads during scroll
- Revert Bootstrap CSS to blocking (media='all') - deferring caused CLS 0.954
- Keep CriticalBootstrapService available for future optimization
- Simplify CriticalCSSHooksRegistrar to only use CriticalCSSService
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Created CriticalCSSService (singleton) that queries BD directly in wp_head
- Service generates CSS BEFORE components render (priority 1)
- Renderers check is_critical flag and skip inline CSS if true
- Made generateCSS() public in Renderers for CriticalCSSService to use
- Removed CriticalCSSCollector pattern (timing issue with WordPress)
Flow:
1. wp_head (priority 1) → CriticalCSSService::render()
2. Service queries BD for components with visibility.is_critical=true
3. Generates CSS using Renderer->generateCSS() methods
4. Outputs: <style id="roi-critical-css">...</style>
5. When Renderers execute, they detect is_critical and omit CSS inline
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
PROBLEMA:
- wp_head() se ejecuta ANTES de que los componentes rendericen
- CriticalCSSCollector estaba vacío al momento de inyectar en <head>
- Componentes retornaban solo HTML sin CSS → sitio sin estilos
SOLUCIÓN:
- Eliminar lógica condicional de is_critical en render()
- Siempre incluir CSS inline con el componente (comportamiento anterior)
- Campo is_critical reservado para futura implementación con output buffering
Archivos modificados:
- NavbarRenderer.php
- TopNotificationBarRenderer.php
- HeroRenderer.php
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
El ins.adsbygoogle tenia width 0 porque el contenedor padre
no tenia ancho definido. Esto causaba el error
"No slot size for availableWidth=0" de AdSense.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Anchor Ads: Cambiar de visibility:hidden a transform:translateY()
para que AdSense pueda medir dimensiones del slot
- Vignette Ads: Solo mostrar overlay cuando data-ad-status="filled"
- Mover card Exclusiones a columna izquierda en admin
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Anchor Ads:
- Ocultos por defecto via CSS (opacity: 0, visibility: hidden)
- Solo se muestran cuando AdSense llena el slot (clase .ad-loaded)
- Ya no aparece espacio en blanco si no hay anuncio
Vignette Ads:
- Agregados tamaños: 728x90, 970x250, 970x90, 468x60, 320x100
- Nueva opción "auto" (recomendado) para formato automático
- Renderer actualizado para manejar todos los tamaños
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Agregar watchUnfilledAds() con MutationObserver
- Detectar data-ad-status="unfilled" de AdSense
- Timeout de 5s como respaldo si no hay contenido
- Evitar mostrar espacio en blanco cuando no hay anuncio
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Anchor Ads: anuncios fijos top/bottom con botones minimizar/cerrar
- Vignette Ads: modal fullscreen con triggers configurables
- Schema v1.3.0 con grupos anchor_ads y vignette_ads (18 campos)
- FieldMapper actualizado para persistir settings en BD
- JavaScript para interacción (colapso, cierre, localStorage)
- Soporte para responsive y tamaños fijos en vignette
IMPORTANTE: Ejecutar en servidor remoto:
wp roi-theme sync-component adsense-placement
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Agregar min-width: 170px para evitar corte
- Quitar overflow:hidden que cortaba contenido
- Detectar footer y ocultar rails cuando se acercan
- Transicion suave de opacity para ocultar/mostrar
- Ancho calculado automaticamente: (viewport - container) / 2 - 20px
- 10px margen del viewport + 10px gap al container
- Selector simplificado: solo altura (250-1050px)
- AdSense usa data-full-width-responsive para adaptarse
- Media query actualizada: oculta en pantallas < 1620px
- Added width options: 130px, 140px, 150px, 160px, 300px, 400px, 500px, 600px
- Each width has multiple height options (300, 400, 500, 600, etc.)
- Total of 31 format combinations available
- Updated Schema, Renderer and FormBuilder
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Changed Rail Ads positioning from container-width-based formula to fixed 15px from viewport edges
- Rails no longer move inward when container width is reduced
- Fixes overlap issue when layout width setting changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Formatos: skyscraper (160x600), wide-skyscraper (160x800), half-page (300x600), large-skyscraper (300x1050)
- Distancia desde arriba: 150, 200, 300 (default), 400, 500, 700px
- Cambiar rail_top_offset de text a select con opciones predefinidas
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Nuevo grupo 'Layout y Contenedor' en theme-settings
- Opciones: 1140px, 1200px, 1320px (default), 1400px, 100%
- CSS dinamico aplicado via ThemeSettingsRenderer
- Corregir selectores de hero en Rail Ads (.hero-section, .featured-image-container)
- Agregar setTimeout para esperar carga de DOM
- Aumentar gap de separacion a 30px
- Subir maxTop al 40% del viewport
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>