Rebeca Pal — System design v3 (tokens y decisiones)

Contexto: child theme rebeca-pal de Hello Elementor (v0.2.0) portado del prototipo ~/Documents/rebeca-pal/01-html/ (rp.css/rp.js + RECETARIO.md, validado pixel a pixel contra Figma a 375/1280). Fuentes LOCALES (sin CDN) en assets/fonts/: Manrope 400–800, Lora 700 (+italic), Nanum Pen Script 400, latin + latin-ext, font-display:swap. Precarga Manrope 500 y 800.

Tokens (escala mobile en :root, desktop en @media (min-width:1024px), sin clamp()):

--rp-oro: #B9AE5E;   --rp-oro-txt: #7D6C3E;   --rp-vino: #55191B;
--rp-borgona: #600912; --rp-ciruela: #3D192E; --rp-hueso: #F8F8F6;
--rp-blanco: #FFFFFF; --rp-input: #D9D9D9;    --rp-input-txt: #8E848B;
--rp-nota-txt: #432A37;

Escala clave: h2 40px/ls5.2/lh43 Manrope 800 (footer 30px) · cuerpo 22/2.86/30 (15/1.95/20) · bio 20/1.26/24.5 (14) · libro Lora 700 20px ls0 uppercase · meta 15/1.4 700 · botón 21.25/h47 (18/h38) · nota Nanum 22/ls3.08/lh1.05 · legal 11/lh19. Breakpoints: 768 (carrusel→grid, puntos ocultos) y 1024. Layout: contenido 1100px, gutter 25/40/90, header 110/108, caja de portada 333×412 hueso sin sombra.

Verificado por códigos computados (probe): ficha = 39px/250×388 mobile, 50px/386×600 desktop, Comprar 26px/h71, “Leer más” solo mobile. Kit de Elementor instalado por código (7 colores, 9 tipografías, container 1100) escribiendo la meta _elementor_page_settings del kit activo (update_settings lanza “Access denied” en frontend — NO usarlo).

Claves técnicas:

  • Filtro elementor/frontend/print_google_fonts → false: Elementor no imprime su CSS de Google Fonts; las locales cubren Manrope/Lora/Nanum.
  • CPT libro (slugs voragine, siete-suicidios, relatos-inconscientes) + meta con show_in_rest: rp_genero, rp_anio, rp_compra_url, rp_portada_grande.
  • single-libro.php con clase es-largo en h1 si título >16 caracteres.
  • Carrusel móvil: contenedores data-carrusel + data-puntos, JS assets/js/rp-carrusel.js (defer), CSS .rp-carrusel (grid ≥768).
  • Google Fonts css2: latin-ext es U+0100-02BA (no 02AF); detectar por prefijo U+0100-02; Nanum no tiene latin-ext.

Pendientes de contenido (no bloquean el tema): sinopsis reales de los dos libros, URLs de compra, URLs de redes, aviso de privacidad, portada alta de “Los siete suicidios capitales”, y montar header/footer/home con Theme Builder (instrucciones en el README del tema).


Anexo: montaje 100% editable en Elementor (4.1.3 atomic + Pro)

Para que TODO (home, hero slider, libros carrusel, frases, footer, fichas) sea editable en Elementor se construyó con JSON clásico (widgets clásicos siguen registrados y editables con UI estándar) + plantillas Theme Builder. Generador: ~/Documents/rebeca-pal/tooling/build_v3/build.py + push.php.

Lecciones duras (Elementor 4.1.3, formato clásico guardado a mano):

  • Secciones solo contienen COLUMNAS; las secciones internas van dentro de columnas (sec > col > sec > col > widgets).
  • css_classes en secciones/columnas es STRING; en widgets la clave es _css_classes (también string).
  • Dynamic tags clásicos: settings.__dynamic__[nombre-control] = '[elementor-tag id="x" name="post-title" settings="%7B%7D"]' — NO settings.control.dynamic (crashea wp_kses).
  • update_post_meta hace wp_unslash: guardar _elementor_data con wp_slash(wp_json_encode(...)); usar wp eval-file (wp-cli) para writes con UTF-8 correcto (php CLI negocia latin1).
  • Condiciones Theme Builder: “todo el sitio” = include/general (sin sub); CPT = include/singular/libro (la sub-condición se llama como el CPT); regenerar caché con Conditions_Cache::regenerate().
  • image-carousel clásico usa settings.carousel (GALLERY), no slides.
  • Hero slider = widget Image Carousel + CSS .rp-hero-carousel (aspect 375/706 → 1280/699, bullets blancos posicionados).
  • Orden móvil de secciones con grid: clases en secciones/columnas + display:contents en <1024px (.rp-yosoy-grid, .rp-ficha-grid, .rp-footer-grid).

Anexo 2: hero slider sin swiper (Elementor 4.1.3 atomic)

El widget clásico image-carousel (swiper) NO se inicializa con JSON clásico en Elementor 4.1.3 atomic: el JS del frontend ignora el widget (sin errores en consola, wrapper sin transform, slides colapsados a 150px → el hero se estiraba y “blanqueaba” la página en Firefox ≥1024px).

Solución: el hero se montó con el MISMO mecanismo de carrusel propio del tema (scroll-snap + data-carrusel/data-puntos + rp-carrusel.js): 3 widgets Image dentro de un track .rp-carrusel.rp-hero-carousel + puntos blancos sobrepuestos (.rp-hero .rp-puntos, bottom 19/47px, visibles a todo ancho). Para que NO pase a grid en ≥768 hay que anularlo: .rp-hero-carousel > .elementor-container{grid-template-columns:none;gap:0; grid-auto-flow:column;grid-auto-columns:100%;overflow-x:auto}. Verificado en Firefox headless 900/1024/1280 (bandas de color correctas) y Chromium (rect del hero 1100×601 desktop, 900×1694 mobile).


Anexo 3: pase “perfectionist” (build Elementor vs 01-html)

Problemas del engine atomic 4.1.3 (clásico renderizado por compat) y sus fixes:


Anexo 4: tablet/espaciados (pase v4)

  • Yosoy y ficha: el grid 2 columnas (457/62/549 y 496/60/549) SOLO a ≥1280; entre 768-1279 se apila (orden móvil) — evitaba el solape del tablet (1068px de columnas fijas > contenedor 1024-1279).
  • Hero: proporción horizontal 54.61% por defecto; vertical 188.27% solo <480px (cambio de ratio que el usuario quería para móvil pequeño).
  • Libros desktop: grid repeat(3,minmax(0,1fr)) gap 20 (tarjetas ~353px, +10%), media box width:100%, head con gap 40 y carrusel con margin-top 64.
  • Chevrones en TODOS los sliders (.rp-hero-nav + .rp-carrusel-nav), casi invisibles (opacity .45) + puntos tinta: homogéneo. JS: scrollBy una tarjeta.
  • Frases móvil: nota width 212px (-30%), área de texto inset 30%/9%/14% (+40px), scroll-behavior:smooth + scroll-snap-stop:always en los tracks.
  • Footer: las reglas móviles del grid deben ir en @media(max-width:1023px) (no en el bloque 1279, o el footer se apila en tablet); form de Elementor en fila ≥1024 (flex-direction:row, input 376) / columna móvil; los grupos .elementor-field-group con flex:1 1 376px.
  • Contenedores de sección: el engine deja .elementor-container content-sized (.elementor-container{max-width:1100px} sin width) → fijar width:100% en los contenedores de hero/yosoy/libros/frases/footer y min-width:0 en las columnas de los tracks.
  • Herramienta de medición: MU-plugin wp-content/mu-plugins/rp-probe.php (query ?rp_probe=1), eliminado al terminar.

Anexo 5: cierre (v0.2.2) — 5 arreglos aplicados

  1. Aislamiento del editor: @font-face → assets/css/rp-fonts.css (15 faces); rp-fonts encolada antes de style.css (dependencia); el hook del editor (elementor/editor/after_enqueue_styles) encola SOLO rp-fonts. Verificado: rp-fonts.css?ver=0.2.2 antes de style.css en el frontend.
  2. Notas: el texto se ancla al .elementor-widget-wrap (container-type: inline-size) y la tipografía escala con 7.3cqw/1.02cqw (22px/3.08px a 302px); inset 36%/11%/10%; eliminados --rp-nota-size/--rp-nota-ls y el duplicado .rp-nota__texto.
  3. Alineación: display:contents también en .elementor-widget-wrap (yosoy/footer/ficha) — los order ahora operan (orden móvil h2→regla→bio→ foto→párrafos verificado por top positions); la clase rp-yosoy-regla DEBE ir en el widget, no en el span (si no, order:0 y la regla queda encima del h2); quitado overflow-x:clip de .rp-yosoy (recortaba la cabeza en vertical: clip+visible → visible computa clip); .rp-cabeza display:none base y block solo ≥1280; libros head gap 27 desktop / sub 4px móvil; tarjetas flex column + margin-top:auto botón + título min-height 2.4em (botones alineados); frases carrusel margin-top 64px en tablet (la rotación de las notas no tapa el título); menú hamburguesa <1024 (breakpoint tablet).
  4. Editable: inc/editable.php — CPT frase (rp_papel oro/vino), shortcodes [rp-libros] (año desc, filas de tres row-gap 52, móvil carrusel N-ready) y [rp-frases] (rotación cíclica), [rp-redes] y [rp-legal] desde opciones (admin → Rebeca Pal), email del form vía elementor_pro/forms/new_record, botón Comprar oculto si rp_compra_url vacío, archive-libro.php, i18n con textdomain. Home/footer ahora consumen los shortcodes (nada de contenido estático en plantillas).
  5. Flechas: 0 chevrones (ya eliminados antes); verificado en el DOM.

Causas raíz documentadas: los widgets cuelgan de .elementor-widget-wrap (no de la columna) → display:contents debe cubrir ambos niveles; el engine deja .elementor-container sin width → fijar width:100% en los contenedores de sección; elementor-col-* no aplica en este engine → anchos a mano.


Anexo 6: sliders laterales también en escritorio (v0.2.2+)

El usuario pidió que Libros/Frases deslicen lateralmente en desktop en lugar de retícula estática cuando crezca el catálogo. Cambios:

  • .rp-carrusel > .elementor-container en ≥768: grid-auto-flow:column; grid-auto-columns:333px; column-gap:20px (antes retícula repeat(3,1fr)).
  • scroll-snap-align:start (con tarjetas de ancho fijo, center haría saltar la primera al centro).
  • Puntos visibles en TODOS los anchos (se quitó el display:none de ≥768) — el indicador ahora siempre existe.
  • JS marcar: el paso se calcula de los dos primeros hijos (items[1].offsetLeft - items[0].offsetLeft), no de clientWidth (con tarjetas fijas clientWidth ≠ tarjeta). Index clamp a items.length-1.
  • Con 3 ítems el ancho total (1039px) cabe en 1100 → sin scroll (se ven los 3); con el 4º (1392px) desliza. Comportamiento N-ready.

Anexo 7: ronda de acabado (v0.2.2 final)


Anexo 8: ronda de acabado — verificación contra checklist

Header alineado al contenedor (sección 5): paddings absolutos fuera (83/171); contenedor width:100%/max-width:1100/margin-inline:auto; gutters 25/40/90 con padding_tablet:40 añadido a yosoy/libros/frases/footer (sin él, a 768 y 1024 el header usaba 40 pero las secciones 90 → desalineación). Verificado por rects a 375/480/768/1024/1280/1440/1920: logo.left == contenido.left y menú al ras (3px de cola de letter-spacing). Logo 45/53, alto 108/110, hamburguesa full-width con .rp-header position:relative ✓. fetchpriority=high en el hero vía JS (sin lazy).