/*
 * La Guayaba Creativa — CSS compartido del plugin.
 *
 * SOLO lo que no puede ir inline en el render() de cada widget (ver
 * SPEC-BLOQUES.md §0.8 y §0.5). Nada de estilos de bloque concreto aquí:
 * eso vive en cada widgets/*.php, scopeado con lgc_css_scope( $this->get_id() ).
 * Esto incluye las media queries de breakpoint DE UN BLOQUE (p. ej. la
 * recomposición del hero, el grid-2 de talleres): SPEC-BLOQUES.md las
 * declara dentro del <style> propio de cada widget, no aquí — solo se
 * centralizan fuentes, tokens, keyframes y el reset base, que sí son
 * realmente globales.
 *
 * Fuente de verdad: private/design/La Guayaba Creativa.dc.html <helmet>,
 * contrastado contra private/.dev/frontend/SPEC-BLOQUES.md Parte 0.
 */

/* ---------------------------------------------------------------------
 * 1. @font-face — Peace Sans (display) y Glacial Indifference (texto)
 * ------------------------------------------------------------------- */
@font-face {
	font-family: 'Peace Sans';
	src: url('../fonts/PeaceSans.woff2') format('woff2'),
		url('../fonts/PeaceSans.woff') format('woff');
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: 'Glacial';
	src: url('../fonts/GlacialIndifference-Regular.woff2') format('woff2'),
		url('../fonts/GlacialIndifference-Regular.woff') format('woff');
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: 'Glacial';
	src: url('../fonts/GlacialIndifference-Bold.woff2') format('woff2'),
		url('../fonts/GlacialIndifference-Bold.woff') format('woff');
	font-weight: 700;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: 'Glacial';
	src: url('../fonts/GlacialIndifference-Italic.woff2') format('woff2'),
		url('../fonts/GlacialIndifference-Italic.woff') format('woff');
	font-weight: 400;
	font-style: italic;
	font-display: swap;
}

/* ---------------------------------------------------------------------
 * 2. Custom properties — tokens de marca. Nombre canónico: los "sugeridos"
 *    por SPEC-BLOQUES.md §0.1 (--lg-*). Úsalos en widgets nuevos.
 *
 *    Se mantienen además como ALIAS los nombres --lgc-* (mismos valores):
 *    varios widgets de Home ya completados en paralelo a esta revisión
 *    (class-hero-collage.php, class-tres-pilares.php, class-listado-cursos.php,
 *    class-talleres-chips.php, class-texto-foto-mascota.php) se escribieron
 *    contra --lgc-* antes de que el núcleo se contrastara con la spec. Quitar
 *    el alias les rompería el color en silencio (custom property inexistente
 *    → valor inicial, no un error visible). No lo quites sin re-grepear
 *    `--lgc-` en widgets/ y confirmar que ya no queda ningún uso.
 * ------------------------------------------------------------------- */
:root {
	--lg-coral: #F26A3C;
	--lg-coral-text: #C8471A;
	--lg-olive: #8E9A3C;
	--lg-olive-text: #6E7A2C;
	--lg-yellow: #FFC738;
	--lg-yellow-soft: #FCDF6B;
	--lg-pink: #F2998C;
	--lg-cream: #FFFBF5;
	/* Tinta de marca — historial en 2 pasos, 2026-08-12 (ver
	 * private/.dev/MARCA-REFERENCIA.md):
	 * 1. Sustituido el marrón inventado #2E1A0C/#3B2412 por la tinta real del
	 *    brandbook (#3E3A16), que no llegaba a AA sobre coral/oliva y obligó
	 *    a una segunda tinta oscura (#2F2C11) solo para esos dos fondos.
	 * 2. Pedido de la diseñadora (vía Pedro): nada de marrón, todo del
	 *    brandbook. Consolidado a UNA sola tinta, #2B2F12 — Verde Piel
	 *    #8E9A3C exacto, mismo tono, solo oscurecido (mismo criterio que
	 *    coral-texto/oliva-texto) — que pasa AA sobre los seis colores
	 *    oficiales, incluido el propio Verde Piel (4,50:1, el más ajustado).
	 * Los tres nombres de abajo COINCIDEN A PROPÓSITO en el mismo valor:
	 * se mantienen los tres (no se colapsan en uno) porque distintos widgets
	 * ya escriben contra cada nombre según su papel — texto (--lg-ink),
	 * alias de compatibilidad (--lg-ink-soft) y fondo oscuro/texto pequeño
	 * sobre coral-oliva (--lg-ink-dark). Renombrar cualquiera de los tres
	 * rompería el color en silencio en los widgets que lo usan. */
	--lg-ink: #2B2F12;
	--lg-ink-soft: #2B2F12;
	--lg-ink-dark: #2B2F12;
	--lg-photo-bg: #EFE6DA;

	/* Alias de compatibilidad — ver nota arriba. Mismos valores que arriba. */
	--lgc-coral-marca: var(--lg-coral);
	--lgc-coral-texto: var(--lg-coral-text);
	--lgc-oliva-marca: var(--lg-olive);
	--lgc-oliva-texto: var(--lg-olive-text);
	--lgc-amarillo: var(--lg-yellow);
	--lgc-amarillo-suave: var(--lg-yellow-soft);
	--lgc-rosa: var(--lg-pink);
	--lgc-crema: var(--lg-cream);
	--lgc-cafe-oscuro: var(--lg-ink-dark);
	--lgc-tinta: var(--lg-ink);
	--lgc-tinta-suave: var(--lg-ink-soft);
	--lgc-tinta-oscura: var(--lg-ink-dark); /* alias de compatibilidad — hoy vale lo mismo que --lg-ink, ver nota arriba */
	--lgc-placeholder-foto: var(--lg-photo-bg);
}

/* ---------------------------------------------------------------------
 * 3. Reset — SPEC-BLOQUES.md §0.5, portado literal
 * ------------------------------------------------------------------- */
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
	margin: 0;
	background: var(--lg-cream);
	color: var(--lg-ink-soft);
	font-family: 'Glacial', 'Helvetica Neue', Helvetica, sans-serif;
	-webkit-font-smoothing: antialiased;
	/* Trampa #1 (CLAUDE.md §5 / SPEC §0.5.1): SIEMPRE clip, NUNCA hidden.
	 * `hidden` fuerza el otro eje a `auto`, convierte body en contenedor de
	 * scroll y rompe `position: sticky` — la cabecera se iba con el
	 * contenido. */
	overflow-x: clip;
}

h1, h2, h3 { hyphens: manual !important; -webkit-hyphens: manual !important; }
* { box-sizing: border-box; }
h1, h2, h3, p, span, a, li, label, button { overflow-wrap: break-word; }
img { max-width: 100%; }
a { color: var(--lg-coral-text); text-decoration: none; }
a:hover { color: var(--lg-ink-soft); }
[data-nav] { transition: none !important; }
::selection { background: var(--lg-yellow); color: var(--lg-ink-soft); }
input, textarea, button, select { font-family: inherit; }
input::placeholder, textarea::placeholder { color: rgba(43, 47, 18, .4); } /* tinta de marca #2B2F12, ver nota de la tinta arriba — antes era el marrón inventado #3B2412, no detectado en la primera pasada por no llevar # */

/* Refuerzo más allá del reset literal de §0.5, de bajo riesgo y beneficio
 * universal (documentado como mejora en NUCLEO-PLUGIN.md): SPEC §0.5.3
 * exige min-width:0 en los <select> del formulario para no provocar scroll
 * horizontal en móvil (la opción más larga del desplegable fija un suelo
 * de min-content). Aplicarlo a TODOS los <select> del sitio es un default
 * seguro que evita que un widget lo olvide. */
select { min-width: 0; }

/* Wrapper de página: el "wrapper raíz" que SPEC §0.5.1 exige junto a body
 * (overflow-x:clip, nunca hidden). El theme/plantilla o un widget global
 * lo aplica a su contenedor raíz cuando lo necesite. */
.lg-overflow-guard { position: relative; overflow-x: clip; }

/* ---------------------------------------------------------------------
 * 4. @keyframes — SPEC-BLOQUES.md §0.4.1, literales
 * ------------------------------------------------------------------- */
@keyframes mq {
	from { transform: translate3d(0, 0, 0); }
	to { transform: translate3d(-50%, 0, 0); }
}
@keyframes bob {
	0%, 100% { transform: translateY(0) rotate(-2deg); }
	50% { transform: translateY(-14px) rotate(2deg); }
}
@keyframes spin {
	to { transform: rotate(360deg); }
}

/* ---------------------------------------------------------------------
 * 5. prefers-reduced-motion — red de seguridad puramente CSS. laguayaba.js
 *    ya revela todo de inmediato y no anima nada cuando detecta esta
 *    preferencia (verificado funcionalmente con una simulación jsdom, no
 *    solo por inspección: reveal se resuelve al instante y el parallax
 *    nunca toca `transform`, incluso tras dejar correr todos los timers de
 *    kick() — ver auditoría M7 en NUCLEO-PLUGIN.md); esto cubre el instante
 *    antes de que el JS corra, y las animaciones CSS puras que no dependen
 *    de JS (marquee, mascota bob).
 *
 *    FIX M7 (auditoría de seguridad, private/.dev/audits/AUDITORIA-PLUGIN.md):
 *    este bloque apuntaba a `.lg-marquee__track` y `.lg-mascot--bob`, que
 *    NINGÚN widget emite — no anulaba nada. Comprobado qué clases usan
 *    realmente los widgets con `animation:` (grep sobre widgets/, único
 *    origen de animaciones CSS continuas hoy: class-marquee.php usa
 *    `.lgc-marquee__track`, class-texto-foto-mascota.php usa `.lgc-mascot`)
 *    y anclado ahí. Ambos widgets YA llevan además su propia regla
 *    `prefers-reduced-motion` scopeada correcta — esta capa es defensa en
 *    profundidad (por si un widget futuro reutiliza estas clases sin su
 *    propio `@media`, o alguien borra la regla local por error), no el
 *    único mecanismo. No inventar clases nuevas aquí: si aparece una
 *    animación continua distinta, añadir su clase REAL tras comprobarla en
 *    el widget, igual que se ha hecho con estas dos.
 * ------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	.lgc-marquee__track { animation: none !important; }
	.lgc-mascot { animation: none !important; }
	[data-para] { transform: none !important; }
	/* Cortinilla de transición (sección 6, más abajo): sin animación ni
	 * clic-interceptado, la página navega directo. Requisito de la propia
	 * declaración de accesibilidad del sitio (RD 1112/2018). */
	html::after { display: none !important; }
}

/* ---------------------------------------------------------------------
 * 6. Cortinilla de transición entre páginas — recuperada de Prioridad B
 *    a petición expresa de la clienta (la echó en falta a la primera; ver
 *    private/.dev/qa/COMPARACION-LEGALES-ANIMACIONES.md). Reproduce la
 *    del Design Component (`.dc.html`, función `go()`): coral opaco a
 *    pantalla completa con el logo en crema centrado, sube .42s / sale
 *    .55s, `cubic-bezier(.76,0,.24,1)`.
 *
 *    QUÉ SE QUITÓ Y POR QUÉ: el `@view-transition { navigation: auto }`
 *    que había aquí antes. Los pseudo-elementos `::view-transition-*`
 *    de Chromium se pintan en el "top layer" del navegador — por ENCIMA
 *    de cualquier z-index normal, incluido el 9999 de esta cortinilla.
 *    Dejarlo activo arriesgaba que el cross-fade nativo asomara por
 *    encima de la cortinilla durante la navegación en Chromium. Esta
 *    cortinilla ya cubre la transición en TODOS los navegadores, no solo
 *    los que soportan la API nativa, así que no hace falta y es mejor
 *    quitarlo que arriesgar el solape.
 *
 *    ARQUITECTURA — por qué es un pseudo-elemento (`html::after`) y no
 *    un `<div>`: este archivo carga en `<head>`, de forma bloqueante
 *    (WordPress no lo difiere) — disponible desde el primer fotograma de
 *    CUALQUIER página. `laguayaba.js`, en cambio, va en el footer con
 *    `defer`: para cuando corre, la página ya se pintó. El sitio tiene
 *    URLs reales (no la SPA del DC), así que el efecto se parte en dos
 *    mitades que ocurren en dos cargas de documento DISTINTAS:
 *      1) clic en un enlace interno → JS sube la cortinilla sobre la
 *         página ACTUAL y navega (laguayaba.js, sección Cortinilla);
 *      2) la página NUEVA llega con la cortinilla ya puesta y la retira.
 *    Si la mitad 2 dependiera de que JS la construya o la posicione,
 *    llegaría tarde y se vería un fogonazo del contenido antes de que
 *    la cortinilla esté encima — exactamente el parpadeo que hay que
 *    evitar. Con un pseudo-elemento CSS puro, sin ningún `<div>` ni
 *    depender de que el HTML lo incluya, el estado de reposo POR
 *    DEFECTO es "cubriendo, opaco" y una animación CSS (sin JS) la hace
 *    desaparecer sola en cuanto la página pinta.
 *
 *    CONSECUENCIA ACEPTADA (documentada, no descuido): con esto la
 *    cortinilla también se ve brevemente en una carga DIRECTA — URL
 *    tecleada, primera visita, recarga — no solo tras un clic interno.
 *    Es el precio de que la mitad de llegada no dependa de que JS llegue
 *    a tiempo. Quitarlo del todo exigiría leer un `sessionStorage` desde
 *    un script bloqueante en `<head>` (cambio de plantilla PHP, fuera
 *    del alcance de este archivo).
 *
 *    z-index 9999: por encima de TODO lo conocido en el sitio — el botón
 *    de WhatsApp flotante (150), el panel del menú móvil abierto (300,
 *    dentro del contexto de apilamiento del header) y el propio
 *    `.elementor-location-header` (350, sección 8 más abajo). Con margen
 *    amplio a propósito: es justo el tipo de valor "por debajo de lo que
 *    hace falta" que ya ha costado tres bugs de z-index en este
 *    proyecto (ver sección 8).
 * ------------------------------------------------------------------- */
html::after {
	content: '';
	position: fixed;
	inset: 0;
	z-index: 9999;
	background-color: var(--lg-coral);
	background-image: url('../img/logo-cream.png');
	background-repeat: no-repeat;
	background-position: center;
	background-size: clamp(140px, 20vw, 220px) auto;
	pointer-events: none; /* decorativa: nunca bloquea clics ni teclado en el contenido real */
	transform: translate3d(0, 0, 0);
	animation: lgc-curtain-out .55s cubic-bezier(.76, 0, .24, 1) forwards;
}
@keyframes lgc-curtain-out {
	from { transform: translate3d(0, 0, 0); }
	to   { transform: translate3d(0, -101%, 0); }
}

/* laguayaba.js arma la entrada en dos pasos, con reflow forzado entre
 * medias (ver setupCurtain() / armCurtain()):
 *   1) salto instantáneo, sin transición, a translate3d(0,101%,0) —fuera
 *      de pantalla por abajo—, deshaciendo cualquier estado previo
 *      (incluido el -101% de una cortinilla que ya hubiera salido).
 *   2) `transition` activada, transform a 0 — sube y cubre en .42s.
 * Misma dirección que el Design Component: sube desde abajo para
 * cubrir, sale por arriba para descubrir. Nunca al revés. */
html.lgc-curtain-arm::after {
	animation: none;
	transition: none;
	transform: translate3d(0, 101%, 0);
}
html.lgc-curtain-entering::after {
	animation: none;
	transition: transform .42s cubic-bezier(.76, 0, .24, 1);
	transform: translate3d(0, 0, 0);
}
/* Forzado a oculta al instante, sin animar. Dos casos (laguayaba.js):
 *  - `lgc-curtain-restored`: vuelta desde la caché del navegador
 *    (bfcache) vía `pageshow`. Es justo donde se queda "pegada" tapando
 *    la página si no se fuerza: el DOM puede restaurarse congelado a
 *    media animación de entrada.
 *  - `lgc-curtain-off`: dentro del editor de Elementor (iframe de
 *    previsualización) — la cortinilla no debe dispararse nunca ahí. */
html.lgc-curtain-restored::after,
html.lgc-curtain-off::after {
	animation: none !important;
	transition: none !important;
	transform: translate3d(0, -101%, 0) !important;
}

/* ---------------------------------------------------------------------
 * 7. Breakpoint 860 px — recomposición responsive.
 *
 *    Va AQUÍ y no en el CSS scopeado de cada widget porque el diseño lo
 *    resuelve con selectores de ATRIBUTO, no con clases de bloque:
 *    `[data-nav-links]`, `[data-nav-burger]`, `[data-hero="a|b|c"]`… son
 *    un contrato global entre el marcado y esta hoja, igual que
 *    `[data-reveal]` o `[data-para]`. Un widget no puede scopearlos sin
 *    romper ese contrato.
 *
 *    HISTORIA — no volver a quitarlas. Una pasada de reconciliación las
 *    borró de aquí por considerarlas "media queries específicas de bloque",
 *    mientras el docblock de widgets/global/class-cabecera.php seguía
 *    afirmando que vivían en este archivo. Las dos cosas no podían ser
 *    ciertas a la vez y el resultado fue que no las tenía nadie: el nav de
 *    escritorio no se ocultaba nunca, la hamburguesa jamás aparecía y la
 *    portada desbordaba 136 px a 320, 96 a 360 y 68 a 390. La web no era
 *    usable en móvil y NADA lo señalaba: HTTP 200, sin errores de consola,
 *    sin warnings en el log.
 *
 *    Copiadas literales del Design Component aprobado (línea 34 de
 *    `La Guayaba Creativa.dc.html`). Los `!important` son suyos: ganan a
 *    los estilos scopeados que cada widget emite en su render().
 * ------------------------------------------------------------------- */
@media (max-width: 860px) {
	[data-nav-links] { display: none !important; }
	[data-nav-burger] { display: inline-flex !important; }
	[data-hero-collage] { gap: 8px !important; }
	[data-hero="b"] { order: -1 !important; flex: 1 1 100% !important; aspect-ratio: 3/2 !important; }
	[data-hero="a"], [data-hero="c"] { flex: 1 1 46% !important; margin-top: 0 !important; aspect-ratio: 4/3 !important; }
	[data-hero-claim] { margin-top: -2vw !important; }
	[data-hero-title] { font-size: 19vw !important; line-height: .82 !important; }
	[data-grid-2] { grid-template-columns: 1fr 1fr !important; gap: 10px !important; }
	[data-aviso] { font-size: 11px !important; letter-spacing: .08em !important; padding: 8px 16px !important; }
	[data-logo] { width: 58px !important; }
}

/* ---------------------------------------------------------------------
 * 8. Cabecera pegada — el sticky va en el contenedor del Theme Builder.
 *
 *    El widget de cabecera declara `position: sticky` en su propio
 *    elemento, y es correcto, pero NO funcionaba: `sticky` solo se
 *    desplaza dentro de la caja de su contenedor, y toda la cadena de
 *    envoltorios que Elementor pone alrededor del widget mide EXACTAMENTE
 *    lo mismo que la cabecera (121 px los cuatro niveles). Sin recorrido
 *    disponible, se despega en el primer píxel de scroll: medido `top:
 *    -2500` tras bajar 2500 px.
 *
 *    `.elementor-location-header` es el <header> que emite el Theme
 *    Builder y es hijo directo de <body>, así que su bloque contenedor es
 *    la página entera y ahí sí hay recorrido. Es un problema estructural
 *    conocido de Elementor, no una regla suelta mal escrita.
 *
 *    Va en el CSS compartido, no en el widget: el elemento pertenece al
 *    Theme Builder, no al plugin, y ningún widget puede scopearlo.
 *
 *    CORRECCIÓN 2026-08-12 (bug de scope CSS, tercera variante, QA E2E):
 *    esta regla dejaba `z-index: 120` en el propio `.elementor-location-header`
 *    — que, al llevar `position: sticky` + un `z-index` explícito, crea SU
 *    PROPIO contexto de apilamiento. El panel del menú móvil
 *    (`.lgc-menu`, `position: fixed; z-index: 300`) vive DENTRO de ese
 *    `<header>`, así que sus 300 solo cuentan puertas adentro de ese
 *    contexto — a nivel de página, todo el `<header>` (con el menú
 *    abierto incluido) competía con z-index 120. El botón flotante de
 *    WhatsApp (`.lgc-wa-float`, z-index 150, sin ningún antepasado que
 *    cree contexto propio) SÍ compite en el contexto raíz, así que
 *    130>120 y el botón se pintaba POR ENCIMA del panel coral a pantalla
 *    completa — visible en las capturas de QA E2E como un botón verde
 *    "colándose" sobre el menú abierto.
 *
 *    Subido a 350 (por encima de cualquier z-index fijo conocido del
 *    sitio: 150 del WhatsApp flotante, 300 del propio panel) para que el
 *    contexto de apilamiento del `<header>` gane siempre, con margen. Si
 *    en el futuro aparece un elemento `position: fixed` con z-index más
 *    alto que compita con el menú abierto, este valor es el primero que
 *    hay que revisar.
 * ------------------------------------------------------------------- */
.elementor-location-header {
	position: sticky;
	top: 0;
	z-index: 350;
}

/* ---------------------------------------------------------------------
 * 7. Área táctil del selector de idioma de TranslatePress (2026-08-12).
 *
 *    RD 1112/2018 + requisito de la subvención Kit Digital: el selector
 *    tiene que ser usable de verdad, no solo estar. El elemento que
 *    recibe el clic de verdad es `.trp-language-switcher-inner` (33px de
 *    alto medido) — el label visible `.trp-language-item__current` tiene
 *    `pointer-events:none` en el propio CSS de TranslatePress, así que
 *    agrandar el label no serviría de nada. Nunca se toca ningún archivo
 *    de TranslatePress: se posiciona un `::before` invisible con inset
 *    negativo que amplía la zona sensible sin cambiar el tamaño ni el
 *    aspecto visual del selector.
 *
 *    -6px arriba/abajo → 33+6+6 = 45px ≥ 44px mínimo. Cabe de sobra
 *    dentro del padding real del `<nav>` de TranslatePress (11px medidos
 *    con getBoundingClientRect, se usan solo 6) sin que su propio
 *    `overflow:hidden` lo recorte. El ancho no se toca: ya son ~119px,
 *    de sobra por encima de 44px. Por construcción, la caja exterior del
 *    `<nav>` (la que decide si solapa con el WhatsApp flotante) no
 *    cambia ni de tamaño ni de posición — verificado en las 5 anchuras
 *    de todos modos, ver private/.dev/devops/TRANSLATEPRESS.md.
 * ------------------------------------------------------------------- */
.trp-language-switcher-inner { position: relative; }
.trp-language-switcher-inner::before {
	content: "";
	position: absolute;
	top: -6px;
	bottom: -6px;
	left: 0;
	right: 0;
}
