- Add ExclusionFormPartial to CtaBoxSidebarFormBuilder
- Add _exclusions fields to CtaBoxSidebarFieldMapper with types
- Update AdminAjaxHandler to process json_array types via ExclusionFieldProcessor
- Enqueue exclusion-toggle.js in AdminAssetEnqueuer
The exclusion UI now appears in CTA Box Sidebar visibility section,
allowing admins to exclude component from specific categories,
post IDs, or URL patterns.
🤖 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>
- Grid layout col-lg-9 + col-lg-3
- Incluye todos los componentes: hero, featured-image, social-share,
cta-post, related-post, table-of-contents, cta-box-sidebar, contact-form
- Permite que cta-box-sidebar se muestre en páginas cuando show_on_pages=all
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed version from 5.3.2-subset to 5.3.2-subset-2 to invalidate
browser/CDN cache after removing position:relative from .navbar.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Post-process PurgeCSS output to remove position:relative from .navbar,
allowing CriticalCSSService's position:sticky to take effect.
This prevents bootstrap-subset.min.css from overriding the navbar
sticky positioning set by the critical CSS system.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Eliminar position:relative hardcodeado de .navbar en critical-bootstrap.css
para que CriticalCSSService pueda establecer position:sticky según
la configuración sticky_enabled en BD.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remover bootstrap-icons de ROI_DEFERRED_CSS
- Cambiar media='print' a media='all'
- Solo 4.4KB - no impacta PageSpeed significativamente
- Elimina flash/parpadeo de iconos en carga inicial
🤖 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>
- 100.6% era muy pequeño (texto crecia al cargar Poppins)
- 106% era muy grande (texto se achicaba al cargar Poppins)
- 103% es el punto medio para minimizar CLS
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
El archivo bootstrap-subset.min.css (cargado diferido) sobrescribia
--bs-body-font-family con var(--bs-font-sans-serif), ignorando
la definicion en critical-bootstrap.css.
Cambio:
- --bs-body-font-family: var(--bs-font-sans-serif)
+ --bs-body-font-family: "Poppins","Poppins Fallback",sans-serif
Esto garantiza que Poppins se use en todo el sitio.
🤖 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>
- Wrap CustomCSSManager bootstrap in try-catch
- Log success message when WP_DEBUG is enabled
- Log detailed error with file/line on failure
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
El hook after_setup_theme se ejecuta muy temprano, antes de que
WordPress determine el tipo de request. Cambio a 'wp' que se
ejecuta después del query principal.
🤖 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>
- Eliminado Inc/critical-css.php (381 lineas de codigo legacy)
- Eliminado require en functions.php linea 45
- Sistema unificado: CriticalCSSService.php genera CSS dinamico desde BD
The table-layout: fixed without defined column widths broke table layout.
Reverting to investigate proper solution.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix hero badge min-height from 32px to 36px (actual height is 35px)
- Add vertical-align: middle to badge for better alignment
- Add critical CSS for .analisis and .desglose tables:
- table-layout: fixed to prevent reflow
- overflow-x: auto for mobile horizontal scroll
- These changes target CLS 0.117 caused by hero badges
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed font-display from 'swap' to 'optional' in bootstrap-icons
subset CSS to prevent CLS caused by icon font swap during page load.
Fixes CLS 0.115 on hero badges with bi-folder-fill icon.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
font-display: swap causes layout shift when fonts load and replace fallback.
font-display: optional prevents CLS entirely - if font doesn't load in ~100ms,
fallback is used permanently. With preload, fonts should load in time.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Windows case-insensitive but Linux case-sensitive.
Git was tracking lowercase, causing 404s on server.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Rename Assets/fonts/ to Assets/Fonts/
- Update all references in PHP and CSS files
- Consistent with Css, Js, Vendor naming
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
PROBLEM:
- apu-tables-auto-class.js was adding CSS classes to table rows after DOMContentLoaded
- This DOM manipulation caused CLS of 0.692 in Lab Data (PageSpeed Insights)
- body.wp-singular was the main culprit with 0.692 CLS contribution
SOLUTION:
- Added roi_add_apu_row_classes() function in Inc/apu-tables.php
- This applies the same logic server-side during the_content filter
- Classes (section-header, subtotal-row, total-row) are now in HTML from first render
- Disabled the JS script in Inc/enqueue-scripts.php
This should significantly reduce Lab Data CLS (target: < 0.1)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Agrega preload de fuentes criticas (regular, 600) en wp_head priority 1
- Fuentes disponibles antes de que CSS las necesite
- Elimina flash de fuente de respaldo que causa layout shift
CLS body.wp-singular esperado: 0.171 -> ~0
🤖 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>
Adds minimal CSS in <head> before wp_head() to hide navbar-collapse
on mobile before Bootstrap loads. This prevents the 0.245 CLS caused
by Bootstrap calculating dimensions on an element that should be hidden.
The CSS in critical-bootstrap.css was arriving too late (via wp_head)
to prevent the initial layout shift.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
contain:layout on main-content fixed AdSense CLS but broke
navbar-collapse causing 0.575 CLS (total 0.887 vs 0.583 before)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
AdSense injects style="height: auto !important" to main-content
causing CLS 0.354. contain:layout isolates from external re-layouts.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add CSS rule to hide navbar-collapse before Bootstrap JS loads.
This prevents Bootstrap from calculating dimensions on an element
that will be hidden anyway, eliminating 0.245 CLS on mobile.
Target: reduce CLS from 0.479 to ~0.234
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove data-bs-spy, data-bs-target, and data-bs-offset attributes
from body tag in header.php. The target element .toc-container does
not exist, causing Bootstrap ScrollSpy to fail and trigger layout
recalculations that account for 82% of the CLS score (0.946 of 1.147).
Ref: 99.02-investigacion-cls-mobile.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
El min-height:50vh en .site-main causaba un CLS de ~1.5 porque:
- Reservaba 50% del viewport inicialmente
- Cuando el contenido real cargaba, generaba un shift enorme
.site-main ya tiene flex-grow:1 que es suficiente para el layout.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
El path a critical-bootstrap.css usaba 'css' (minúscula) pero
el directorio real es 'Css' (mayúscula). Esto causaba que el
CSS crítico no se cargara en producción (Linux es case-sensitive).
Bug encontrado: El CriticalBootstrapService no inyectaba el CSS
en producción porque file_exists() retornaba false.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>