/**
 * innovalike-cr-card.css
 *
 * Tarjeta de CR (.innovalike-cr-card), réplica en PHP + CSS nativos de los
 * bucles de Elementor "Bucle - CR 1X1 (A)" (template ID 1559, modificador
 * --1x1a) y "Bucle - CR 2X1" (template ID 1431, modificador --2x1). Medido
 * con getComputedStyle sobre el render real en
 * https://innovalike.local/?cat=10 (proyectos-idi) y ?cat=100/101/102 (grupo
 * Mercado) — nunca estimado desde el JSON exportado ni desde una captura.
 *
 * Tamaños naturales (los mismos que los bucles originales):
 * - --1x1a: 320x320px.
 * - --2x1: 655x320px.
 * El escalado para la celda de tabla se hace en innovalike-tables.css
 * (.innovalike-table-thumb--card), no aquí. Ninguna variante se escala aquí.
 *
 * Paso 1 (v1.5.1): variante --1x1a.
 * Paso 2 (v1.5.2): variante --2x1 + badges de ODS opcionales
 * (.listado-ods-cr, solo visibles en :hover — verificado con Playwright
 * sobre el render real: opacity 0→1 + translateY(30px)→0).
 *
 * @package Innovalike
 * @since 1.5.1
 */

/* ==========================================================================
   Base — común a todas las variantes
   ========================================================================== */

.innovalike-cr-card {
    display: block;
    position: relative;
    overflow: hidden;
    background-color: var(--innovalike-bg-white);
    font-family: var(--innovalike-font-family), sans-serif;
    text-decoration: none;
    color: var(--innovalike-text-primary);
    box-sizing: border-box;
    /* El bucle original alinea TODO a la izquierda (text-align: start medido en
       cada nodo). Se fija aquí porque la celda de tabla que la contiene puede
       venir centrada y la tarjeta heredaría ese centrado. */
    text-align: left;
    /* Texto sin espacios salta de línea en vez de desbordar la tarjeta */
    overflow-wrap: anywhere;
    /* Sistema de slots (docs/cr-card/plan-slots-y-semantica.md, D1): el slot
       del tema escala la tarjeta con transform:scale() partiendo de su
       esquina superior izquierda (el lienzo se maqueta SIEMPRE a tamaño
       nativo — 320x320 / 655x320 — y se escala entero, nunca se refluye el
       texto). Sin este origin, scale() por defecto pivota desde el centro y
       la tarjeta escalada no encajaría en la esquina superior izquierda de
       su slot. Inofensivo donde todavía no hay slot (intranet): sin
       transform aplicado, transform-origin no tiene ningún efecto visible. */
    transform-origin: top left;
}

/* [HISTÓRICO] Este comentario describe una colisión con el kit de Elementor
   (.elementor-kit-5), que deja de existir al eliminar Elementor del sitio (ver
   themes/innovalike-theme/docs/plan-eliminar-elementor.md). La regla se
   conserva: es inofensiva y sigue siendo correcta sin el kit.

   Refuerzo de especificidad para cuando la tarjeta es un <a> ($args['link'] =
   true, único caso del frontal público — paso 3 del plan de migración de
   bucles): el kit de Elementor define ".elementor-kit-5 a { color: var(
   --e-global-color-accent) }" con especificidad (0,1,1), que gana a la regla
   base ".innovalike-cr-card { color: ... }" (0,1,0) y pinta TODO el texto
   heredado de la tarjeta (entidad, sector, intro, categoría — ningún elemento
   de la variante 1x1a define su propio color, todos heredan del contenedor)
   del azul "accent" del kit en vez del gris de texto del design system. Con
   $args['link'] = false (<div>, único caso usado hasta el paso 2 — las dos
   tablas de la intranet) el kit no tiene ninguna regla ".elementor-kit-5 div"
   de esa especificidad, así que el bug nunca se manifestó hasta ahora. Mismo
   patrón de refuerzo ya usado en el título (".innovalike-cr-card
   .innovalike-cr-card__titulo", ver más abajo) — doble selector de clase
   (0,2,0) para ganar de forma fiable, sin depender del orden de aparición en
   la cascada frente a la regla del kit. */
.innovalike-cr-card.innovalike-cr-card {
    color: var(--innovalike-text-primary);
}

/* Reset defensivo: el contenedor de la tarjeta hereda de la intranet y del kit
   de Elementor (que sigue cargando por header/footer). Sin esto, cualquier
   regla de alineación del contexto se cuela dentro de la tarjeta. */
.innovalike-cr-card *,
.innovalike-cr-card *::before,
.innovalike-cr-card *::after {
    box-sizing: border-box;
    text-align: inherit;
}

/* El cursor depende de si la tarjeta enlaza o no, que es justo lo que
   distingue a sus dos consumidores:
   - intranet ($args['link'] = false): puramente ilustrativa, no navega a
     ninguna parte, así que cursor por defecto;
   - frontal público ($args['link'] = true): el título lleva un <a> real,
     extendido a toda la tarjeta con un stretched link (D4, ver más abajo),
     tiene que verse clicable con la mano en toda su superficie.
   El elemento raíz es SIEMPRE <article> (D4) — ya no cambia de tag según
   $args['link'] como antes (<a>/<div>), así que el cursor ya no puede
   resolverse por selector de etiqueta: se activa por la presencia real del
   <a> dentro del título, con :has(). */
.innovalike-cr-card {
    cursor: default;
}

.innovalike-cr-card:has(.innovalike-cr-card__titulo a) {
    cursor: pointer;
}

/* Stretched link (D4): con $args['link'] = true el título lleva un <a> real
   (el único enlace de la tarjeta — accesible, anuncia el título al lector de
   pantalla), extendido a toda la superficie de la tarjeta con ::after en vez
   de envolver el <article> completo en un <a> (que sería HTML inválido junto
   con el resto de elementos interactivos y además perdería la semántica de
   <article>). No hace falta declarar z-index/position en .listado-ods-cr
   aquí: la regla ya existente más abajo (bloque "Badges de ODS") ya lo
   define como position:absolute + z-index:4, por encima del z-index:1 de
   este stretched link — los badges siguen recibiendo el :hover que los
   muestra sin quedar bloqueados por esta capa.

   [HISTÓRICO — el kit de Elementor deja de existir tras la migración, ver
   themes/innovalike-theme/docs/plan-eliminar-elementor.md; el prefijo de
   especificidad se conserva porque es inofensivo.]
   ⚠️ Bug encontrado y corregido en verificación: el kit de Elementor define
   ".elementor-kit-5 a { color: var(--e-global-color-accent) }" con
   especificidad (0,1,1) — EXACTAMENTE la misma que tenía aquí
   ".innovalike-cr-card__titulo a" (0,1,1), así que el empate lo ganaba el
   kit (carga después en la cascada) y el <a> del título salía azul pese a
   que el <h2> que lo envuelve mide correctamente rgb(0,0,0) por
   getComputedStyle — el bug es invisible si solo se mide el <h2>, hay que
   medir el <a> en sí. Mismo patrón de colisión ya documentado para el <h2>
   suelto más abajo (".innovalike-cr-card .innovalike-cr-card__titulo").
   Solución idéntica: prefijar con la clase de la tarjeta para subir a
   (0,2,1), por encima del kit de forma fiable. */
.innovalike-cr-card .innovalike-cr-card__titulo a {
    color: inherit;
    text-decoration: none;
}

.innovalike-cr-card__titulo a::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
}

/* Borde inferior de 1px con el color de la categoría — medido en el <a> raíz
   del bucle 1559/1431 real: "1px solid rgb(93,171,70)" en proyectos-idi (el
   mismo verde del badge, la entidad y el sector). Va en la base porque el
   original lo aplica al contenedor raíz de ambas variantes; el color por
   categoría se sobreescribe en el bloque de color del final del fichero.
   box-sizing:border-box (ya en la base) mantiene los 320px/655px exactos. */
.innovalike-cr-card {
    border-bottom: 1px solid var(--innovalike-cat-proyectos);
}

/* ==========================================================================
   Variante --1x1a (bucle 1559, 320x320px)
   ========================================================================== */

.innovalike-cr-card--1x1a {
    width: 320px;
    height: 320px;
}

/* .__media (figure) ahora contiene la imagen Y la banda de categoría
   (<figcaption>, D4 — es literalmente su leyenda), apiladas en flujo normal:
   180px de imagen + 21px de categoría = 201px, medido en el bucle original
   (donde la categoría era el primer hijo de .__body, justo debajo de la
   imagen — mismo resultado visual, distinto padre en el árbol). Antes de este
   cambio la figura solo contenía la imagen (180px); el resto de las medidas
   de este fichero (título, intro, sector) se ajustan más abajo para
   descontar los 21px que la categoría se lleva de dentro de .__body. */
.innovalike-cr-card--1x1a .innovalike-cr-card__media {
    width: 320px;
    height: 201px;
    overflow: hidden;
    /* Reset del margin nativo de <figure> — el original no tiene ninguno. */
    margin: 0;
}

.innovalike-cr-card--1x1a .innovalike-cr-card__media img {
    display: block;
    width: 100%;
    height: 180px;
    object-fit: cover;
}

/* .__body ya NO incluye la categoría (ahora en .__media) ni el sector (ahora
   en .__footer): solo entidad + título/intro. Altura: 320 total - 201 media -
   24 footer (sector) = 95px, con 4.2px de aire igual que el original
   (95 = 90.8 de contenido real + 4.2 de slack, ver .__titulointro). */
.innovalike-cr-card--1x1a .innovalike-cr-card__body {
    display: flex;
    flex-direction: column;
    width: 320px;
    height: 95px;
    padding: 0 var(--innovalike-spacing-sm);
    box-sizing: border-box;
    overflow: hidden;
}

/* Badge de categoría — ahora <figcaption> dentro de .__media (D4), pero con
   la MISMA apariencia visual que antes: banda a ancho completo, radio solo en
   la esquina inferior derecha, color por categoría vía modificador
   .innovalike-cr-card--cat-{slug} (ver bloque de colores más abajo). */
.innovalike-cr-card--1x1a .innovalike-cr-card__categoria {
    /* Padding a AMBOS lados: el original solo declaraba el izquierdo, así que la
       banda verde llegaba al filo derecho de la tarjeta. Con el radio de 25px en
       la esquina inferior derecha, el texto necesita ese respiro para no quedar
       pegado al borde cuando la etiqueta es larga. */
    padding: 0 var(--innovalike-spacing-sm);
    height: 21px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    background-color: var(--innovalike-cat-proyectos);
    /* Medido: la banda ocupa el ancho completo (320px) con el radio solo en la
       esquina inferior derecha (25px). No es una píldora ajustada al texto. */
    border-bottom-right-radius: var(--innovalike-radius-xxl);
}

/* Color de categoría, igual que el sector — medido en el bucle 1559 real:
   rgb(93,171,70) para proyectos-idi, el mismo verde del badge y del borde
   inferior de la tarjeta (ver .innovalike-cr-card--1x1a más arriba). */
.innovalike-cr-card--1x1a .innovalike-cr-card__entidad {
    margin: 0;
    padding: 7px 0 5px;
    font-size: 14px;
    font-weight: 600;
    line-height: 14px;
    color: var(--innovalike-cat-proyectos);
}

/* Caja de título + intro con ALTURA FIJA de 70px y overflow:hidden — es
   exactamente lo que hace el bucle original (medido: la caja del shortcode
   [innovalike-get-cr campo="titulointro"] va de y=227 a y=297 dentro de la
   tarjeta, 70px, con overflow:hidden, y el sector arranca justo después en
   y=297, FUERA de esta caja).

   NO se usa flex aquí: título e intro van en flujo normal y es el recorte de
   la caja el que decide cuánto se ve. Una versión anterior repartía el espacio
   con flex (`.__titulo` con flex-shrink:0 + `.__intro` con flex:1 1 0), y con
   un título de 3 líneas (54px) dentro de una caja de 64.8px la intro se
   quedaba con 0px de altura: el texto estaba en el DOM pero era invisible.
   Con altura fija y flujo normal, un título de 3 líneas deja 16px = 1 línea de
   intro (igual que el original), y un título corto deja ver más líneas. */
.innovalike-cr-card--1x1a .innovalike-cr-card__titulointro {
    height: 70px;
    flex-shrink: 0;
    overflow: hidden;
    /* Flujo normal (sin flex): el título ocupa sus líneas y la intro va justo
       debajo. El reparto de las 4 líneas lo hace el clamp de la intro, que JS
       ajusta por tarjeta — ver la nota de .__intro sobre por qué flex aquí
       rompería la elipsis. */
}

/* El título SIEMPRE se lee completo: no se recorta ni se limita a N líneas.
   Crece las líneas que necesite y es el cuerpo (.__intro) el que cede espacio.
   flex-shrink:0 es lo que garantiza que no lo comprima el flex del contenedor.
   [HISTÓRICO — lo que sigue sobre ".elementor-kit-5" describe el kit de
   Elementor, que deja de existir tras la migración (ver
   themes/innovalike-theme/docs/plan-eliminar-elementor.md); el color
   explícito se conserva porque es inofensivo y correcto sin el kit.]
   color explícito (Bloque E del paso 3, docs/cr-card/plan-migracion-bucles.md):
   ".elementor-kit-5 h2 { color: var(--e-global-color-primary) }" (0,1,1) es
   una regla que aplica DIRECTAMENTE sobre <h2>, así que ninguna regla de
   herencia sobre un ancestro (por alta que sea su especificidad, incluida
   ".innovalike-cr-card.innovalike-cr-card") puede ganarle — solo otra regla
   que también aplique directamente sobre .innovalike-cr-card__titulo con
   especificidad igual o mayor. Este selector ya es (0,2,0), suficiente. Sin
   este color explícito el título del archive público hereda el azul "kit
   primary" en vez del texto normal — el kit de Elementor solo carga en el
   frontal (header/footer), nunca en la intranet, así que este bug no se
   manifestó en los pasos 1/2 (ambos solo probados con $args['link']=false en
   la intranet, sin kit cargado). Mismo patrón ya usado por la variante --2x1
   (ver más abajo, __titulo con --innovalike-text-black desde el paso 2). */
.innovalike-cr-card--1x1a .innovalike-cr-card__titulo {
    font-size: 15px;
    line-height: 18px;
    flex-shrink: 0;
    color: var(--innovalike-text-black);
    /* margin 0: el <h2> del original no tiene margen (medido), pero el tema
       aplica "8px 0 16px" a los h2 del frontal. Esos 24px extra empujaban la
       intro fuera de la caja de 70px y la dejaban invisible con títulos de 3
       líneas — el mismo síntoma que ya tenía el reparto por flex anterior. */
    margin: 0;
    /* Tope de 3 líneas (54px de los 70px de la caja). No es un límite
       arbitrario: es el máximo que el original llega a mostrar, y fijarlo hace
       que el reparto título/intro sea DETERMINISTA — que es lo que permite a
       la intro recortar con su propio clamp (y por tanto pintar la elipsis) en
       vez de que la recorte la caja. Ver el comentario de .__intro abajo. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* El cuerpo va en flujo normal justo detrás del título (mismo mecanismo que
   el original): lo que quepa en los 70px de la caja se ve, y el resto lo
   recorta el clamp o, en su defecto, el overflow:hidden del padre.
   margin-bottom 14.4px medido en el <p class="intro"> original.

   Puntos suspensivos: `-webkit-box` + `-webkit-line-clamp`, el mismo
   mecanismo del original — el navegador añade la elipsis por su cuenta al
   recortar. (Nota para futuras mediciones: esa elipsis NO aparece en el DOM
   ni en `textContent`, la pinta el motor de render; buscarla en el texto da
   un falso negativo, hay que mirar la regla CSS.)

   El clamp de la intro es de UNA línea, y el del título de 3 (ver arriba).
   Esa combinación es la única que hace que la elipsis se vea SIEMPRE: el
   recorte lo hace siempre el clamp de la intro, nunca el `overflow` de la
   caja — que es el caso en el que el navegador no pinta nada.

   Medido sobre los 6 CRs reales del archive:
   - título de 3 líneas (54px): a la intro le quedan 1.03 líneas en la caja.
     Con clamp 2 desbordaba 15px y recortaba la caja → sin elipsis.
   - título de 2 líneas: sobran 18px (una línea sin usar). Es el coste
     aceptado a cambio de que la elipsis aparezca en todos los casos; con
     clamp 2 esos 18px se aprovechaban, pero los títulos de 3 líneas se
     quedaban sin indicador de texto cortado.
   `:has()` no sirve para distinguir los dos casos: detecta estructura, no
   cuántas líneas ocupa un texto. Tampoco flex ni max-height (ambos
   comprimían la intro a ~0px, el bug del punto 8). */
.innovalike-cr-card--1x1a .innovalike-cr-card__intro {
    font-size: 13px;
    line-height: 15.6px;
    /* Sin margen inferior: título + intro deben sumar 4 líneas dentro de los
       70px de la caja (decisión del usuario, 2026-09-21). El peor caso
       (3 título + 1 intro) mide 54 + 15,6 = 69,6px — cabe justo, pero los
       14,4px de margen que tenía antes lo sacaban fuera. */
    margin: 0;
    /* ⚠️ NADA de `flex` aquí. Un primer intento dio a la intro
       `flex: 1 1 auto` para que absorbiera el hueco del título: repartía bien
       las 4 líneas, pero al convertirla en hija flex el navegador
       "blockifica" su `display` y EL CLAMP DEJA DE EXISTIR — la altura
       resultante salía fraccionaria (1,03 / 2,18 / 3,33 líneas), el recorte
       lo hacía el `overflow` y la elipsis no se pintaba.
       El reparto lo decide ahora JS, que mide las líneas reales del título y
       fija el clamp complementario de la intro (ver cr-archive.js del tema,
       `ajustarReparto`). Por defecto 1 línea, que es el caso más frecuente y
       el que deja el layout correcto si JS no llega a ejecutarse. */
    /* Negro explícito, igual que el título y que la intro de la --2x1 (medido
       rgb(0,0,0) en el bucle original). Sin esta declaración la intro heredaba
       --innovalike-text-primary (#333) del contenedor de la tarjeta: la --2x1
       sí lo declaraba desde el paso 2, la --1x1a nunca. */
    color: var(--innovalike-text-black);
    /* El clamp es quien RECORTA y quien pinta la elipsis. Su valor lo ajusta
       JS por tarjeta (data-lineas-intro), para completar 4 líneas junto al
       título. 1 es el valor por defecto: el reparto más frecuente (3+1) y un
       fallback correcto si JS no llega a ejecutarse. */
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Reparto de las 4 líneas, aplicado por JS sobre el contenedor de la tarjeta
   según cuántas ocupe el título (ver cr-archive.js, `ajustarReparto`):
   título 1 → intro 3, título 2 → intro 2, título 3 → intro 1.
   Se hace por atributo y no con `flex` a propósito (ver la nota de .__intro):
   la intro debe conservar su `-webkit-box` para que el clamp pinte los "…". */
.innovalike-cr-card--1x1a[data-lineas-intro="2"] .innovalike-cr-card__intro {
    -webkit-line-clamp: 2;
}

.innovalike-cr-card--1x1a[data-lineas-intro="3"] .innovalike-cr-card__intro {
    -webkit-line-clamp: 3;
}

/* .__footer (nuevo, D4) envuelve SOLO el sector — antes vivía como último
   hijo de .__content, anclado abajo con margin-top:auto dentro del mismo
   flex column que entidad/título/intro. Ahora es su propia caja, ya no
   comparte flex context con nada: el padding (7px arriba, 5px abajo = 24px
   de alto) es lo único que necesita para reproducir la misma posición y
   tamaño exactos (320 = 201 media + 95 body + 24 footer). */
.innovalike-cr-card--1x1a .innovalike-cr-card__footer {
    display: block;
    /* Alineado con el resto del contenido (entidad/título/intro, todos a 10px):
       antes el footer iba a left:0 con 320px de ancho, así que el sector y su
       línea separadora quedaban pegados a los bordes de la tarjeta mientras el
       texto de encima respetaba su margen. Mismo patrón que la --2x1, que ya
       ponía el padding en su propio __footer. */
    padding: 0 var(--innovalike-spacing-sm);
    box-sizing: border-box;
}

.innovalike-cr-card--1x1a .innovalike-cr-card__sector {
    padding: 7px 0 5px;
}

/* CR sin imagen destacada (habitual en borradores): banda neutra con un icono,
   para que la maqueta se lea igual y se vea que falta la imagen. Resuelto en
   CSS en vez de con un JPG real — assets/images/cr-placeholder.jpg es una
   maqueta vertical de 869x2233 y 888 KB, pensada para el modal de vista previa;
   repetirla en 25 filas serían ~22 MB de descarga para una miniatura de 96px.
   Ya no es el propio contenedor de la imagen (antes .__image--placeholder
   cargaba también .__image, que traía el 100% de ancho/alto): ahora es un
   <span> suelto dentro de .__media, así que fija su propio tamaño — igual al
   que tenía la imagen real (320x180, la franja de categoría de 21px sigue
   pintándose debajo, como <figcaption>, tanto con imagen real como sin ella). */
.innovalike-cr-card--1x1a .innovalike-cr-card__image--placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 320px;
    height: 180px;
    background-color: var(--innovalike-border-lighter);
    border-bottom: 1px solid var(--innovalike-border-light);
}

.innovalike-cr-card--1x1a .innovalike-cr-card__image--placeholder .dashicons {
    font-size: 56px;
    width: 56px;
    height: 56px;
    line-height: 1;
    color: var(--innovalike-border-light);
}

/* Los badges de ODS de la --1x1a solo aparecen con $args['ods']=true (ninguna
   variante los pinta por defecto). Layout medido en el contenedor .todosods
   del bucle original: ver el bloque compartido al final del fichero. */

/* ==========================================================================
   Variante --2x1 (bucle 1431, 655x320px)
   ========================================================================== */

/* Sistema de slots y semántica (D4): la --2x1 comparte el MISMO árbol DOM que
   la --1x1a (figure > img+figcaption, body > entidad+titulointro(titulo,intro),
   footer > sector) — no dos estructuras distintas como antes (había __row,
   __textcol y un __footer que hacía de intro+sector compartido). Aquí se
   consigue reproducir la disposición horizontal original SOBRE ese mismo
   árbol con CSS Grid: cada elemento se coloca en la celda que le corresponde
   con independencia de su posición en el DOM.

   Grid de la tarjeta (655x320), medido en el bucle original (ver §3.6 del
   plan de slots): columnas 10px (padding izq.) | 335px (texto) | 300px
   (imagen) | 10px (padding der.); filas 21px (categoría) | 10px (separador,
   el antiguo margin-top de .row) | 170px (fila texto+imagen) | 119px (pie:
   intro+sector). Sin cambios en las medidas, solo en cómo se declaran. */
.innovalike-cr-card--2x1 {
    display: grid;
    grid-template-columns: var(--innovalike-spacing-sm) 335px 300px var(--innovalike-spacing-sm);
    grid-template-rows: 21px var(--innovalike-spacing-sm) 170px 119px;
    width: 655px;
    height: 320px;
}

/* .__media (figure) deja de ser una caja propia: sus dos hijos (imagen y
   figcaption de categoría) se colocan cada uno en su celda del grid de arriba,
   como si fueran hijos directos de la tarjeta — display:contents no cambia
   nada visualmente, solo saca la caja de la figura del cálculo de layout
   (mismo recurso que ya usa .listado-ods-cr con position:absolute más abajo:
   reordenar sin depender de dónde vive el nodo en el DOM). */
.innovalike-cr-card--2x1 .innovalike-cr-card__media {
    display: contents;
}

/* Banda de categoría — mismo patrón que la --1x1a (ancho completo, radio solo
   en la esquina inferior derecha), pero a 655px en vez de 320px. Ahora
   colocada por grid en vez de ser el primer flex-item del root. */
.innovalike-cr-card--2x1 .innovalike-cr-card__categoria {
    grid-column: 1 / 5;
    grid-row: 1;
    /* Padding a ambos lados, igual que la --1x1a (ver nota allí). */
    padding: 0 var(--innovalike-spacing-sm);
    display: flex;
    align-items: center;
    justify-content: flex-start;
    background-color: var(--innovalike-cat-proyectos);
    border-bottom-right-radius: var(--innovalike-radius-xxl);
}

/* Imagen — celda de la columna 3 (300px) y fila 3 (170px), exactamente donde
   vivía dentro de .__row. object-fit CONTAIN (no cover, a diferencia de la
   --1x1a): la imagen real del bucle (768x432, ratio 16:9 ≈ 1.78) casi
   coincide con la caja (300x170, ratio ≈ 1.76), así que en la práctica no se
   ven bandas vacías con las imágenes reales del entorno — pero el modo es
   CONTAIN, no COVER, y con una imagen de ratio muy distinto sí aparecerían. */
.innovalike-cr-card--2x1 .innovalike-cr-card__media img {
    grid-column: 3;
    grid-row: 3;
    display: block;
    width: 300px;
    height: 170px;
    overflow: hidden;
    object-fit: contain;
    border-bottom-right-radius: var(--innovalike-radius-xxl);
}

.innovalike-cr-card--2x1 .innovalike-cr-card__image--placeholder {
    grid-column: 3;
    grid-row: 3;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 300px;
    height: 170px;
    background-color: var(--innovalike-border-lighter);
    border-bottom: 1px solid var(--innovalike-border-light);
}

.innovalike-cr-card--2x1 .innovalike-cr-card__image--placeholder .dashicons {
    font-size: 56px;
    width: 56px;
    height: 56px;
    line-height: 1;
    color: var(--innovalike-border-light);
}

/* .__body — columna de texto (335px, proyecto/entidad + título), celda
   columna 2 / fila 3. Mismo contenido y mismo comportamiento que el antiguo
   .__textcol: centrada verticalmente (justify-content:center, medido), ancho
   fijo 335px. overflow:hidden como cinturón de seguridad: un título muy largo
   (varias líneas a 25px) podría superar los 170px de alto disponibles; se
   recorta en vez de desbordar la celda y descuadrar el resto de la tarjeta. */
.innovalike-cr-card--2x1 .innovalike-cr-card__body {
    grid-column: 2;
    grid-row: 3;
    display: flex;
    flex-direction: column;
    /* La ENTIDAD se queda arriba (alineada con el borde superior de la imagen)
       y el TÍTULO se centra verticalmente en el espacio que queda por debajo
       (decisión del usuario, 2026-09-21). Por eso el contenedor sigue en
       flex-start: el centrado es cosa del título, no del bloque entero —
       ver `.__titulo` más abajo, que crece con flex y centra su texto. */
    justify-content: flex-start;
    width: 335px;
    height: 170px;
    overflow: hidden;
}

.innovalike-cr-card--2x1 .innovalike-cr-card__entidad {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    line-height: 16px;
    color: var(--innovalike-cat-proyectos);
}

/* [HISTÓRICO] El kit de Elementor (.elementor-kit-5) deja de existir tras la
   migración (ver themes/innovalike-theme/docs/plan-eliminar-elementor.md); el
   prefijo se conserva porque es inofensivo.
   Prefijada con .innovalike-cr-card (en vez de la clase sola) para ganar de
   forma fiable a ".elementor-kit-5 h2 { color: ... }" — el kit global de
   Elementor sigue cargando en toda página de intranet (header/footer) y esa
   regla, de baja especificidad pero sobre la etiqueta simple <h2>, pisaba el
   color medido en el bucle original si no se refuerza aquí (mismo problema ya
   documentado en el paso 1, v1.5.1). El título SIEMPRE se lee completo, sin
   clamp: crece las líneas que necesite (la caja de la tarjeta no colapsa
   porque el resto del layout usa alturas fijas y flex, no depende de esta
   caja). line-height medido: 25px (=1em de 25px, coincide con el "line-height:
   1em" declarado en Elementor). */
.innovalike-cr-card--2x1 .innovalike-cr-card__titulo {
    margin: 0;
    font-size: 25px;
    font-weight: 700;
    line-height: 25px;
    color: var(--innovalike-text-black);
    /* El título ocupa todo el alto que deja la entidad y centra su texto en
       él (decisión del usuario, 2026-09-21): la entidad se queda arriba,
       alineada con el borde superior de la imagen, y el título queda
       ópticamente centrado en el resto de la columna.
       `flex: 1` + centrado propio, en vez de centrar el bloque entero desde
       `.__body`, que también habría bajado la entidad. */
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

/* .__titulointro envuelve título + intro en el árbol PHP (igual que la
   --1x1a), pero aquí la intro necesita salir a ancho completo (635px, medido)
   mientras el título se queda en la columna de 335px — algo que el árbol
   original de Elementor lograba con dos bloques independientes, uno dentro de
   .row (335px) y otro fuera de ella (635px). display:contents en
   .__titulointro dispensa de crear una caja propia: el título se queda dentro
   de .__body (celda columna 2) sin cambios, y la intro se posiciona aparte
   (ver más abajo) usando position:absolute respecto a .innovalike-cr-card,
   que ya es position:relative desde la regla base del fichero. */
.innovalike-cr-card--2x1 .innovalike-cr-card__titulointro {
    display: contents;
}

/* Intro — ancho completo (635px = 655 - 2×10 de padding), posicionada en
   absoluto porque su ascendiente real (.__body, 335px) es más estrecho que
   ella: el árbol original de Elementor la sacaba de la columna de texto por
   completo, así que aquí se reproduce con position:absolute en vez de
   negative margins (más frágil: dependería del ancho exacto del padre en
   cada momento). top:201px = 21 (categoría) + 10 (separador) + 170 (fila),
   el mismo punto donde arrancaba el antiguo .__footer.

   ⚠️ Bug encontrado y corregido en verificación (capturado con pantalla real,
   no solo con números — mismo tipo de fallo ya documentado en v1.5.4 puntos
   10/11 y regla 2 de §0 del plan de slots): esta regla tenía `height: 119px`
   fijo, pensado como "sobra de margen" para el clamp. Pero con
   position:absolute + una altura EXPLÍCITA mayor que el contenido clampado,
   el recorte real lo hacía el `overflow:hidden` de esa altura fija (119px =
   6.2 líneas a 19.2px), no el `-webkit-line-clamp:4` — el texto se veía
   partido a mitad de línea, sin elipsis, solapando el sector. El clamp por
   líneas SOLO manda cuando la caja no tiene una altura mayor impuesta desde
   fuera: sin `height` (con position:absolute, se ajusta por shrink-to-fit al
   contenido ya clampado), la caja mide justo lo que ocupan sus 4 líneas +
   el padding-top, que es exactamente lo medido en el original (~94px:
   15px padding-top + 4×19.2px = 91.8px, redondeado por el motor de render a
   los ~94px del baseline). */
.innovalike-cr-card--2x1 .innovalike-cr-card__intro {
    position: absolute;
    top: 201px;
    left: var(--innovalike-spacing-sm);
    width: 635px;
    margin: 0;
    padding-top: 15px;
    box-sizing: border-box;
    font-size: 16px;
    font-weight: 400;
    line-height: 19.2px;
    color: var(--innovalike-text-black);
    /* Mismo mecanismo de elipsis que la --1x1a (ver allí): 4 líneas, que es
       lo que cabe en los ~94px de alto que le deja el footer a 19.2px de
       interlineado. Sin height fijo (ver nota del bug arriba): la caja se
       ajusta por shrink-to-fit al contenido ya clampado, así que es SIEMPRE
       el clamp quien recorta y pinta la elipsis, nunca el overflow de una
       altura impuesta desde fuera. */
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Texto de muestra (CR sin cuerpo redactado): atenuado y en cursiva para que
   no se confunda con contenido real guardado. Compartido con la --1x1a. */
.innovalike-cr-card__intro.is-placeholder {
    color: var(--innovalike-text-secondary);
    font-style: italic;
}

/* .__footer (nuevo, D4) envuelve SOLO el sector — celda columna 1/5, fila 4
   (655x119, empieza justo donde termina la fila de texto+imagen). Antes el
   sector compartía esta misma caja con la intro y se anclaba al fondo con
   margin-top:auto (empujado por la intro, que ocupaba el espacio con
   flex:1 1 0 por encima); ahora la intro vive fuera de esta caja (ver arriba,
   position:absolute), así que el propio footer se encarga de anclar el
   sector abajo con flex — mismo resultado, sector queda en el mismo punto
   exacto medido en el original (offsetTop 295 relativo a la tarjeta, 94px
   dentro de esta caja de 119px). */
.innovalike-cr-card--2x1 .innovalike-cr-card__footer {
    grid-column: 1 / 5;
    grid-row: 4;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 0 var(--innovalike-spacing-sm);
    box-sizing: border-box;
}

.innovalike-cr-card--2x1 .innovalike-cr-card__sector {
    padding: 7px 0 5px;
}

/* ==========================================================================
   Badges de ODS — común a todas las variantes (opcionales, $args['ods'])
   ========================================================================== */

/* Contenedor de los badges — réplica del bloque `.todosods` del bucle
   original, medido con getComputedStyle sobre el render real de la Home
   (bucles 1559 y 1431 vivos):
     position: absolute; inset: auto 0 0 0;  (ancho completo, pegado al pie)
     height: 100px;  padding: 10px;  z-index: 4;
     display: flex; flex-direction: column;
     justify-content: flex-end;  align-items: flex-start;  ← IZQUIERDA
     background-image: linear-gradient(180deg, #FFFFFF00 0%, {cat} 75%);
     opacity: 0 → 1 y translateY(30px) → 0 al :hover, transición 0.5s.

   El degradado va del transparente (arriba) al color de la categoría (75% de
   los 100px de alto), no al revés: se funde con la tarjeta por arriba y es
   sólido al pie. El color por categoría se sobreescribe en el bloque de color
   del final del fichero. */
/* Prefijado con .innovalike-cr-card (0,2,0) y no con la clase suelta: el
   shortcode legacy [innovalike-get-ods-cr] (Innovalike_Shortcodes::get_ods())
   imprime en línea un ".listado-ods-cr { display:flex; gap:10px }" suelto.
   Hasta F4 de themes/innovalike-theme/docs/plan-mejoras-rendimiento-semantica.md
   el tema (theme-custom.css) tenía además un ".listado-ods-cr { display:grid;
   max-width:300px }" global que esta regla neutralizaba con
   width/max-width/grid-template-columns; al retirarse esa hoja sobraban. */
.innovalike-cr-card .listado-ods-cr {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 100px;
    box-sizing: border-box;
    padding: var(--innovalike-spacing-sm);
    z-index: 4;
    display: flex;
    flex-wrap: wrap;
    align-content: flex-end;
    justify-content: flex-start;
    align-items: flex-end;
    gap: var(--innovalike-spacing-sm);
    background-image: linear-gradient(
        180deg,
        rgba(255, 255, 255, 0) 0%,
        var(--innovalike-cat-proyectos) 75%
    );
    /* Oculto por defecto: en el render real (Playwright, hover real) opacity
       pasa de 0 a 1 con translateY(30px) → 0 al :hover. Solo CSS, sin JS. */
    opacity: 0;
    transform: translateY(30px);
    transition: opacity 0.5s cubic-bezier(0.34, 1.56, 0.64, 1),
        transform 0.5s cubic-bezier(0.34, 1, 0.64, 1);
    pointer-events: none;
}

.innovalike-cr-card:hover .listado-ods-cr {
    opacity: 1;
    transform: translateY(0);
}

.innovalike-ods-item__badge {
    width: 45px;
    height: 45px;
    border-radius: 50%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: var(--innovalike-text-white);
}

.innovalike-ods-item__badge-label {
    display: block;
    font-size: 9px;
    font-weight: 700;
    line-height: 1;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.innovalike-ods-item__badge-numero {
    display: block;
    font-size: 18px;
    font-weight: 700;
    line-height: 0.8;
}

/* ==========================================================================
   Cabecera de categoría / entidad+título / sector — texto común a --1x1a y
   --2x1 (mismo tamaño de fuente en el badge de categoría y en el sector; el
   tamaño de entidad/título/intro SÍ difiere entre variantes y se define en
   cada bloque de variante más arriba)
   ========================================================================== */

/* display:block por el mismo motivo que .__sector span — evitar que herede el
   line-height del contenedor y engorde la caja. */
.innovalike-cr-card__categoria-label {
    display: block;
    font-size: 14px;
    font-weight: 600;
    /* Cursiva medida en el <span> de la categoría del bucle original
       (font-style: italic + text-transform: uppercase). */
    font-style: italic;
    line-height: 14px;
    color: var(--innovalike-text-white);
    text-transform: uppercase;
}

/* display:block — siendo inline, el span generaba una caja de línea con el
   line-height heredado del contenedor (21px) en lugar de su propio 12px, y el
   bloque del sector medía 34.5px en vez de los 24px del bucle original. */
.innovalike-cr-card__sector span {
    display: block;
    font-size: 12px;
    font-weight: 600;
    /* Cursiva medida en el <span>/<p> del sector del bucle original. */
    font-style: italic;
    line-height: 12px;
    color: var(--innovalike-cat-proyectos);
}

/* ==========================================================================
   Color por categoría (badge + entidad/proyecto + sector comparten color)
   ========================================================================== */

/* Fondo en :hover — color "light" de la categoría (corrección post-Fase 8 de
   themes/innovalike-theme/docs/plan-eliminar-elementor.md). Réplica del
   contenedor raíz de los bucles 1559 (7cd97ac) y 1431 (cc3b997), leído de su
   _elementor_data: background_hover_color = globals/colors?id=4918d77, que
   theme-custom.css (HEAD) redefinía por categoría en .elementor-element
   (proyectos-idi → ce07cd1 #DFEEDA, productos/servicios → 99ddde4 #FDF4E6), y
   background_hover_transition 1.2 → "transition: background 1.2s" del .e-con.
   Solo en tarjetas con enlace (frontal): la miniatura de la intranet no enlaza
   y no reacciona al hover, igual que el cursor (ver arriba). El resto de
   ajustes de hover del original (box-shadow, blur) no se aplicaban: sus
   controles no estaban activados (sin box_shadow_hover_box_shadow_type ni
   css_filters_hover_css_filter). */
.innovalike-cr-card {
    transition: background-color 1.2s;
}

.innovalike-cr-card:has(.innovalike-cr-card__titulo a):hover {
    background-color: var(--innovalike-cat-proyectos-light);
}

.innovalike-cr-card--cat-productos:has(.innovalike-cr-card__titulo a):hover,
.innovalike-cr-card--cat-servicios:has(.innovalike-cr-card__titulo a):hover,
.innovalike-cr-card--cat-eventos:has(.innovalike-cr-card__titulo a):hover {
    background-color: var(--innovalike-cat-productos-light);
}

.innovalike-cr-card--cat-productos .innovalike-cr-card__categoria,
.innovalike-cr-card--cat-servicios .innovalike-cr-card__categoria,
.innovalike-cr-card--cat-eventos .innovalike-cr-card__categoria {
    background-color: var(--innovalike-cat-productos);
}

.innovalike-cr-card--cat-productos .innovalike-cr-card__entidad,
.innovalike-cr-card--cat-servicios .innovalike-cr-card__entidad,
.innovalike-cr-card--cat-eventos .innovalike-cr-card__entidad,
.innovalike-cr-card--cat-productos .innovalike-cr-card__sector span,
.innovalike-cr-card--cat-servicios .innovalike-cr-card__sector span,
.innovalike-cr-card--cat-eventos .innovalike-cr-card__sector span {
    color: var(--innovalike-cat-productos);
}

/* Borde inferior de 1px (ver la regla base) — mismo color de categoría. */
.innovalike-cr-card--cat-productos,
.innovalike-cr-card--cat-servicios,
.innovalike-cr-card--cat-eventos {
    border-bottom-color: var(--innovalike-cat-productos);
}

/* Degradado del bloque de ODS en hover (ver .listado-ods-cr) — mismo color.
   Doble clase de tarjeta para mantener la especificidad (0,3,0) por encima de
   la regla base prefijada, sin depender del orden de la cascada. */
.innovalike-cr-card.innovalike-cr-card--cat-productos .listado-ods-cr,
.innovalike-cr-card.innovalike-cr-card--cat-servicios .listado-ods-cr,
.innovalike-cr-card.innovalike-cr-card--cat-eventos .listado-ods-cr {
    background-image: linear-gradient(
        180deg,
        rgba(255, 255, 255, 0) 0%,
        var(--innovalike-cat-productos) 75%
    );
}

/* El antiguo breakpoint @media (max-width: 1024px) que reacomodaba la --2x1
   al formato vertical de la --1x1a se elimina (sistema de slots y semántica,
   Bloque B punto 4 — docs/cr-card/plan-slots-y-semantica.md): contradecía D2
   (la relación de aspecto se respeta siempre, la tarjeta nunca se deforma).
   Con escalado proporcional (D1) ya no hace falta: el slot del tema escala la
   --2x1 entera manteniendo sus 655x320 nativos a cualquier ancho, y en móvil
   (D8) el propio slot decide si la --2x1 ocupa 1 o 2 columnas — la tarjeta en
   sí no cambia de forma en ningún viewport. */
