/**
 * Estilos del bloque `ipropanel/projects-browser` (S6.2).
 *
 * Nodo `233:4095` (listado+mapa) precedido por la barra `257:819`
 * (contador + toggle). Ancho de contenido con el mismo patrón que
 * `featured-projects`/`projects-hero`: `wide-size` + `section-padding-inline`
 * fluido, que a 1280px real resuelve a los 1040px del nodo — regla del
 * proyecto de no usar los valores literales de `contentSize`/`wideSize`.
 */

/* Fondo de la sección: `233:4095` declara `#030813` en desktop y el frame
   mobile lo confirma (muestreo del render de `297:4445`: `rgb(3,8,19)` a
   ancho completo, de borde a borde y hasta el footer). El bloque no lo
   declaraba, y como ni `body` ni `html` aportan fondo, sobre la plantilla
   ensamblada el panel del listado —que es `rgba(255,255,255,0.1)`, pensado
   para leerse sobre oscuro— quedaba blanco sobre blanco. Aislado en una
   página de prueba el defecto no era observable: solo aparece al ensamblar
   (S6.5). Es el mismo hallazgo D-15 que S4.8 corrigió en `promo-banner`,
   con el mismo remedio y el mismo token. */
.ipropanel-projects-browser {
	background-color: var( --wp--preset--color--near-black );
}

/* La caja de contenido va en `__inner` y no en la raíz, para que el fondo
   de arriba llegue a los bordes del viewport: es el patrón de los otros 11
   bloques del tema (`promo-banner`, `members-logos`, `advantages-grid`…).
   `padding-block` del nodo: `pt-[32px] pb-[80px]` de `233:4095`. */
.ipropanel-projects-browser__inner {
	max-width: var( --wp--style--global--wide-size );
	margin-inline: auto;
	padding-inline: var( --wp--preset--spacing--section-padding-inline );
	padding-block: 32px 80px;
}

.ipropanel-projects-browser__barra {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 12px 34px;
	margin-bottom: 16px;
	background-color: var( --wp--preset--color--dark-blue-footer );
	border-radius: var( --wp--custom--border-radius--full );
	box-shadow: var( --wp--preset--shadow--shadow-toggle-bar );
}

/*
 * `line-height: 18px` es valor de los DOS nodos de la barra (`257:823`
 * desktop y `297:5345` mobile declaran ambos Montserrat Bold 12/18), no
 * un valor mobile — por eso vive acá y no en la media query. S6.2 lo
 * había omitido y el contador quedaba en 15px (interlineado normal de
 * 12px). En desktop la omisión no se veía porque el alto de la barra lo
 * fija el toggle (26px de botón + 3px de padding × 2 = 34); en mobile,
 * donde el toggle no existe, el contador es lo único que la sostiene y
 * sin esto la píldora da 39 contra los 42 del nodo `297:5342`.
 */
.ipropanel-projects-browser__contador {
	font-family: var( --wp--preset--font-family--montserrat );
	font-weight: 700;
	font-size: var( --wp--preset--font-size--form-label );
	line-height: 18px;
	color: var( --wp--preset--color--neutral-white );
}

.ipropanel-projects-browser__toggle {
	display: flex;
	gap: 6px;
	padding: 3px;
	background-color: var( --wp--custom--color--gray-input-bg );
	border: 1px solid var( --wp--custom--color--gray-input-border );
	border-radius: var( --wp--custom--border-radius--full );
}

.ipropanel-projects-browser__toggle-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	padding: 0;
	background: none;
	border: 0;
	border-radius: var( --wp--custom--border-radius--full );
	cursor: pointer;
}

.ipropanel-projects-browser__toggle-btn--activo {
	background-color: var( --wp--preset--color--primary-light-blue );
}

/* Estado hover / `:active` del botón INACTIVO (S11.1, 2026-08-11) —
   DECISIÓN PROVISIONAL, depende de `CD-A5` (abierta).

   El archivo pinta un único estado del toggle (`257:824`) y no dice qué pasa
   al pasar por encima del botón que no está seleccionado. Se extiende el
   sistema con lo que el propio control ya hace: el icono pasa a
   `primary-light-blue`, que es el color al que va a quedar el botón si se
   pulsa. O sea el hover ANTICIPA el resultado del clic en vez de inventar un
   tercer color, y por eso el fondo no se toca: pintar el fondo teal aquí
   volvería el botón indistinguible del que ya está activo.

   El `:not( --activo )` NO es defensivo, es obligatorio: sin él la regla del
   hover (dos clases + pseudo-clase) le gana por especificidad a la del icono
   blanco del botón activo (dos clases), y el botón seleccionado quedaría con
   el icono teal sobre su propio fondo teal — invisible. */
@media ( hover: hover ) {
	.ipropanel-projects-browser__toggle-btn:not( .ipropanel-projects-browser__toggle-btn--activo ):hover .ipropanel-projects-browser__toggle-icono {
		background-color: var( --wp--preset--color--primary-light-blue );
	}
}

.ipropanel-projects-browser__toggle-btn:not( .ipropanel-projects-browser__toggle-btn--activo ):active .ipropanel-projects-browser__toggle-icono {
	background-color: var( --wp--preset--color--primary-light-blue );
}

/*
 * Silueta del icono (14 × 14, el tamaño del nodo `257:826`/`257:831`). El SVG
 * llega desde `render.php` en `--ipropanel-toggle-icono` y aquí solo hace de
 * máscara: el color es el `background-color`, o sea un token.
 *
 * El archivo pinta un único estado (`257:824`: vista mapa activa con el icono
 * blanco sobre `primary-light-blue`, vista grid inactiva con `#030813` sobre
 * el gris del grupo) y no dice qué pasa al invertirlo. Se extiende el sistema
 * con esos mismos dos valores intercambiados —el icono del botón activo es
 * blanco, el del inactivo `near-black`—, que es la lectura literal de lo que
 * el diseño ya hace. Pregunta registrada en `docs/INTERACTIONS.md`.
 */
.ipropanel-projects-browser__toggle-icono {
	width: 14px;
	height: 14px;
	background-color: var( --wp--preset--color--near-black );
	mask: var( --ipropanel-toggle-icono ) no-repeat center / 100% 100%;
	-webkit-mask: var( --ipropanel-toggle-icono ) no-repeat center / 100% 100%;
	transition: background-color var( --wp--custom--motion--duration-estado ) var( --wp--custom--motion--easing-estado );
}

.ipropanel-projects-browser__toggle-btn--activo .ipropanel-projects-browser__toggle-icono {
	background-color: var( --wp--preset--color--neutral-white );
}

/* La fila listado+mapa (`233:4096`). Se llamaba `__inner` hasta S6.5, que
   necesitó ese nombre para el wrapper de ancho —el que lleva la caja en
   todos los bloques del tema— y la renombró por lo que es. */
.ipropanel-projects-browser__columnas {
	display: flex;
	gap: 34px;
}

/*
 * **La sombra interna NO va acá** (`S11.5b`). `233:4097` declara fill
 * `rgba(255,255,255,0.1)`, radio 16 y `pl-16 pr-8 py-16`, y **ninguna sombra**;
 * el `inset 0 4px 4px rgba(0,0,0,0.25)` lo declara solo el panel de la vista
 * grid (`320:297`). El tema lo tenía en la regla base, así que la vista lista
 * pintaba una sombra que el archivo no pide en ninguno de sus dos breakpoints
 * —en 414 la media query ya la anulaba, que es por qué solo se veía en 1280—.
 * Pasa a la regla de `--vista-grid`, que es el único nodo que la declara.
 */
.ipropanel-projects-browser__listado {
	flex: 0 0 436px;
	padding: 16px 8px 16px 16px;
	background-color: var( --wp--custom--color--hover-light );
	border-radius: var( --wp--custom--border-radius--lg );
}

/* Los 406 y el `padding-inline-end: 16px` son los tres hijos que el nodo
   `233:4097` declara en fila: la columna de cards (`233:4098`, 384), un
   `gap: 16` y la barra (`233:4302`, 6px de ancho — track `233:4304`
   #e8e8e8 y thumb `233:4305`). 384 + 16 + 6 = 406. Antes el `<ul>` medía
   384 clavados y su padding era 0, así que la barra se pintaba ENCIMA del
   borde derecho de las cards mientras sobraban 28px muertos a su derecha
   (RD-12, S16.2).
   El padding es 22 y no 16 porque la barra se pinta en el borde derecho
   de la caja de padding SIN ocupar ancho de layout (barra superpuesta):
   22 = los 16 de hueco del nodo + los 6 de la propia barra, y así la card
   conserva sus 384. Medido, no deducido: con `padding-right: 16px` la
   card se iba a 390 y el hueco quedaba en 10. `scrollbar-gutter: stable`
   se probó primero y es no-op en este modelo — no reserva nada — así que
   se quitó en vez de dejarlo como amuleto. */
.ipropanel-projects-browser__cards {
	width: 406px;
	height: 561px;
	overflow-y: auto;
	display: flex;
	flex-direction: column;
	gap: 16px;
	list-style: none;
	margin: 0;
	padding: 0 22px 0 0;
	scrollbar-width: thin;
	scrollbar-color: var( --wp--preset--color--dark-blue-gradient ) var( --wp--custom--color--scrollbar-track );
}

.ipropanel-projects-browser__cards::-webkit-scrollbar {
	width: 6px;
}

/*
 * `RD-11` — quitar las flechas de la barra de scroll.
 *
 * No había ninguna flecha en el tema: las pinta Blink por su cuenta. En cuanto
 * se estiliza `::-webkit-scrollbar` y no se declaran sus botones, el motor
 * dibuja los suyos —visibles en Windows/Linux; en macOS, con overlay
 * scrollbars, no aparecen, y por eso no se vieron al construir esto y sí en la
 * revisión del diseñador—. El nodo `233:4302` solo dibuja track (`233:4304`) y
 * thumb (`233:4305`), así que quitarlos es alinearse con el archivo.
 *
 * NO son botones enfocables ni operan el listado por teclado, de modo que esto
 * no le quita nada a la alternativa accesible al mapa (V18.c): el `<ul>` se
 * sigue recorriendo con Tab sobre las cards. Verificado antes de tocar nada —
 * cero `::-webkit-scrollbar-button` y cero `scrollBy`/`scrollTop` en el tema.
 *
 * El ancho y el alto en 0 acompañan al `display: none` a propósito: el
 * `display` basta en Blink, pero un motor que solo honre la métrica dejaría
 * los botones ocupando extremo de track y el thumb arrancaría más abajo.
 */
.ipropanel-projects-browser__cards::-webkit-scrollbar-button {
	display: none;
	width: 0;
	height: 0;
}

.ipropanel-projects-browser__cards::-webkit-scrollbar-track {
	background-color: var( --wp--custom--color--scrollbar-track );
	border-radius: var( --wp--custom--border-radius--full );
	box-shadow: var( --wp--preset--shadow--shadow-scrollbar-track );
}

.ipropanel-projects-browser__cards::-webkit-scrollbar-thumb {
	background-color: var( --wp--preset--color--dark-blue-gradient );
	border-radius: var( --wp--custom--border-radius--full );
	box-shadow: var( --wp--preset--shadow--shadow-scrollbar-thumb );
}

/*
 * Panel del mapa. La proporción es la del nodo `553:2327` (570×606) y el
 * fondo el del nodo interno `553:1916`: `#00647d` con radio 16 — o sea el
 * token `primary-dark-blue`, cuyo valor coincide EXACTO con el fill del
 * archivo (`theme.json` §palette), así que no hace falta token nuevo. Hasta
 * S7.1 esto era `hover-light`, que sobre el `#030813` de la sección se leía
 * casi negro: hallazgo **D-57** de `QA-RECONCILIACION.md` §17, aquí resuelto.
 *
 * `position: relative` ancla los controles de zoom y `overflow: hidden` hace
 * que el radio recorte el canvas de Leaflet, que es un hijo absoluto.
 *
 * **El alto es fijo y el ancho fluido, y no al revés (corrección post-S7.4).**
 * Hasta aquí esto era `aspect-ratio: 570 / 606` + `max-width: 570px`, los dos
 * literales del nodo medido a 1280. Pero el ancho de la sección NO es fijo: la
 * barra y el `__inner` usan `wide-size` con padding fluido, así que pasan de
 * 1040 a 1200 entre 1280 y 1440. El tope de 570 dejaba entonces el mapa **160
 * px corto respecto del borde derecho de la barra** —invisible a 1280, donde
 * los dos valores coinciden por construcción—. Con `flex: 1` sin tope, el mapa
 * absorbe el sobrante y los dos bordes vuelven a coincidir a cualquier ancho.
 * El 606 se conserva tal cual: el listado se estira a él por `stretch`, que es
 * exactamente lo que ya pasaba. La contrapartida está en el JS: un panel más
 * ancho no debe acercar la cámara — ver `calcularVistaInicial()` en
 * `src/js/mapa-proyectos.js`.
 *
 * `isolation: isolate` (S7.3b) crea aquí el contexto de apilamiento que hasta
 * ahora creaba el canvas con su `z-index: 0`. El motivo es el orden de pintado:
 * los panes de Leaflet van de 200 a 700 y los controles son HERMANOS del
 * canvas, así que con el contexto en el canvas los controles quedaban por
 * encima de TODO lo interno, card de previsualización incluida. Con el contexto
 * un nivel más arriba, canvas y controles compiten en la misma escala y el
 * orden sale correcto de una sola vez: overlay (400) < pines (600) <
 * controles (650) < card (700). Y los 700 de Leaflet siguen sin poder escaparse
 * del panel —que era lo que el contexto del canvas evitaba: sin él, el mapa
 * podía pasar por encima del header sticky al hacer scroll.
 */
.ipropanel-projects-browser__mapa {
	position: relative;
	isolation: isolate;
	flex: 1;
	height: 606px;
	overflow: hidden;
	background-color: var( --wp--preset--color--primary-dark-blue );
	border-radius: var( --wp--custom--border-radius--lg );
}

/*
 * Vista grid (S6.3) — nodo `320:295`, contenedor `320:296` dentro del frame
 * de página `320:214`. Es el mismo DOM que la vista lista+mapa reestilado:
 * las cards no se duplican, `view.js` solo cambia clases.
 *
 * El panel del grid (`320:297`) usa exactamente los dos tokens que el
 * listado ya consume — `hover-light` es su `rgba(255,255,255,0.1)` y
 * `shadow-listado-inset` su `inset 0 4px 4px rgba(0,0,0,0.25)` —, así que
 * es el mismo `__listado` a ancho completo y no hay tokens nuevos.
 *
 * El grid **crece con el contenido**, no tiene scroll interno: la sección
 * mide 909 = 32 + 820 (panel) + 57, y un contenedor con scroll propio no
 * haría crecer a su padre. El `665` del nodo `320:296` es altura de frame
 * obsoleta —sus propios hijos miden 820 y 723,2 y lo desbordan— y no se usa
 * como referencia. Ver pregunta abierta #33 de `docs/INTERACTIONS.md`.
 */

.ipropanel-projects-browser--vista-grid .ipropanel-projects-browser__mapa {
	/*
	 * `display: none` y no `visibility`/`opacity`: la vista inactiva no debe
	 * ocupar espacio NI ser alcanzable por teclado.
	 * Sprint 7: cuando esto tenga un mapa Leaflet, volver a la vista lista
	 * exige `map.invalidateSize()` — Leaflet inicializado dentro de un
	 * `display: none` mide 0 y renderiza roto.
	 */
	display: none;
}

.ipropanel-projects-browser--vista-grid .ipropanel-projects-browser__listado {
	flex: 1 1 auto;
	/* Inset del wrapper `320:1513` dentro del panel de 1040: (1040-972,747)/2
	   = 33,63 ≈ 34, el mismo valor que ya usan la barra y el gap del inner. */
	padding: 34px;

	/* La sombra interna es de ESTE panel y de ningún otro: `320:297` la
	   declara y `233:4097` no (S11.5b). */
	box-shadow: var( --wp--preset--shadow--shadow-listado-inset );
}

.ipropanel-projects-browser--vista-grid .ipropanel-projects-browser__cards {
	display: grid;
	grid-template-columns: repeat( 3, 1fr );
	/* Fila 1 del nodo (`589:2165`): gap de columna 32, gap de fila 24,319.
	   La fila 2 (`538:10587`) trae 29,931 — drift del archivo, se normaliza
	   al valor de la fila 1 y se reporta en la pregunta abierta #33. */
	gap: 24px 32px;
	/* Todas las filas miden lo que la más alta (corrección post-S7.4). Sin
	   esto el alto solo se iguala DENTRO de cada fila —que es lo que hace
	   el `stretch` del grid— y basta un título de tres líneas en una fila
	   para que esa quede más alta que las demás. Con la semilla actual
	   coincidían las tres por casualidad, no por regla. */
	grid-auto-rows: 1fr;
	/* Se anula la geometría de la columna con scroll de la vista lista
	   —incluido el hueco de 16px contra la barra (RD-12), que aquí no
	   existe porque no hay barra. */
	width: auto;
	height: auto;
	padding: 0;
	overflow: visible;
}

/*
 * Las cards de una misma fila miden lo mismo. El `<li>` ya se estira solo
 * (es ítem de grid), pero sin esto la `<a>` de adentro conserva su alto
 * natural y una tarjeta con título de 3 líneas deja a sus vecinas cortas.
 * El nodo lo dice explícito: `589:2166` envuelve la card con `self-stretch`
 * y la propia card va a `h-full`. El relleno interior ya lo resuelve
 * `--vertical` con su `__body { flex: 1 1 auto }`.
 *
 * **Y la segunda regla, que faltaba (corrección post-S7.4).** Con el `<li>`
 * como flex pero sin dimensionar la card, la `<a>` es un ítem de flex con
 * `width: auto`, o sea ancho de contenido: como `__image` es `width: 100%`
 * sobre una `<img>` absoluta, quien fija ese ancho acaba siendo el texto más
 * largo. Medido con la semilla, las 8 cards de la misma grilla iban de 216 a
 * 303 px. Es exactamente el patrón que `featured-projects` sí tiene completo
 * (`blocks/featured-projects/style.css`), del que aquí solo se había copiado
 * la mitad.
 */
.ipropanel-projects-browser--vista-grid .ipropanel-projects-browser__item {
	display: flex;
}

.ipropanel-projects-browser--vista-grid .ipropanel-projects-browser__item .ipropanel-project-card {
	width: 100%;
	height: 100%;
}

/*
 * Mobile (S6.4) — frame `297:3937`, sección `297:4445`.
 *
 * Todo lo de arriba es desktop y queda acotado acá: `__columnas` (fila con
 * gap 34), `__listado` (columna fija de 436 con panel) y `__cards`
 * (384×561 con scroll interno), más las cuatro reglas de `--vista-grid`.
 * El `padding-block` de `__inner` también difiere y se redeclara.
 *
 * El diseño mobile es: píldora del contador, mapa a ancho de columna y
 * listado de 1 columna debajo, fluyendo con la página. **Sin toggle**
 * (D1) y **sin scroll interno**: el scroll interno es exclusivo de la
 * columna izquierda de la vista lista+mapa en desktop.
 *
 * **Especificidad, no escalada sino igualada.** Las reglas de
 * `--vista-grid` son (0,2,0), así que las tres que compiten con ellas
 * (`__mapa`, `__listado`, `__cards`) se scopean a la raíz del bloque
 * para empatar en (0,2,0) y ganar por orden de fuente. El resultado es
 * que la geometría mobile NO depende del estado de vista: la clase
 * `--vista-grid` puede sobrevivir a un cambio de breakpoint y quedar
 * inerte, sin que haga falta ninguna guarda de `matchMedia` en
 * `view.js` que duplicaría el 767 en otro archivo. Mismo patrón que
 * `site-header` con `__nav-wrapper[hidden]` dentro de su media query.
 * Ver la nota sobre clases de estado en `docs/TECHNICAL.md`.
 *
 * Medidas del archivo: barra→mapa 32 (`297:5341` termina en 85,
 * `630:11604` arranca en 117), mapa→cards 32 (490,125 → 522,125) y gap
 * entre cards 16 — este último ya es el de base y no se repite.
 */
@media ( max-width: 767px ) {
	.ipropanel-projects-browser__barra {
		margin-bottom: 32px;
	}

	/*
	 * El nodo mobile de la barra (`297:5341`) es idéntico al desktop
	 * (`257:819`) salvo que no dibuja el grupo de botones. Se oculta el
	 * contenedor entero y no los botones sueltos, para que se vaya
	 * también su `role="group"` con su `aria-label`. `display: none` y
	 * no `visibility`/`opacity`: un control que no existe a este ancho
	 * no debe ocupar espacio NI ser alcanzable por Tab — mismo criterio
	 * que S6.3 fijó para el mapa oculto de la vista grid. El markup no
	 * cambia: es una decisión de breakpoint, no de estado, así que no
	 * corresponde `[hidden]`.
	 */
	.ipropanel-projects-browser__toggle {
		display: none;
	}

	/* La sección mobile (`297:4445`, 1698,65 de alto) abre 40 sobre la barra
	   y cierra 64 bajo la última card (1698,65 − 1634,65, donde 1634,65 es
	   el fin de `630:12014`). Distintos de los 32/80 de desktop. */
	.ipropanel-projects-browser__inner {
		padding-block: 40px 64px;
	}

	.ipropanel-projects-browser__columnas {
		flex-direction: column;
		gap: 32px;
	}

	/* El mapa va ARRIBA del listado (`INTERACTIONS.md` §Mapa de Colombia).
	   Se reordena por CSS y no moviendo el DOM: en desktop el orden de
	   lectura correcto es listado → mapa.
	   **Revisión de tabulación pendiente desde S6.3, resuelta en S7.4:
	   se queda como está.** El panel ya tiene sus dos controles de zoom,
	   así que en mobile se tabula el listado completo antes de llegar a
	   ellos aunque el mapa se vea primero. No es un desajuste que valga
	   la pena arreglar: son los únicos focusables del panel, operan un
	   canvas cuyo contenido va `aria-hidden` (V19.b) y V18.c declara el
	   listado como la alternativa accesible COMPLETA al mapa — recorrer
	   primero el contenido y después el control accesorio es orden
	   significativo. Mover el DOM rompería el orden correcto de desktop
	   (listado a la izquierda, mapa a la derecha) sin ganar nada.
	   Verificado en el QA de S7.4: +0 focusables nuevos en mobile.
	   La proporción no cambia entre breakpoints —350,959/373,125 del nodo
	   `630:11604` es el mismo 0,9406 que el 570/606 del `553:2327`—, pero
	   aquí es el ANCHO el que lo fija la columna y el alto el que se
	   deduce, al revés que en desktop: de ahí que `aspect-ratio` viva en
	   esta media query desde la corrección post-S7.4 y no en la base. */
	.ipropanel-projects-browser .ipropanel-projects-browser__mapa {
		order: -1;
		display: block;
		flex: 0 0 auto;
		height: auto;
		aspect-ratio: 570 / 606;
	}

	/* Sin panel: el contenedor del listado mobile (`630:12014`) es un
	   flex column con gap 16 y nada más — ni fondo, ni padding, ni radio,
	   a diferencia del `233:4097` de desktop.
	   El `box-shadow: none` que había acá **se retira, no se olvida**: la
	   sombra ya no está en la regla base desde S11.5b, así que esta línea
	   anulaba algo que a este ancho no existe. Se queda documentado porque
	   una anulación que no anula nada es indistinguible de una que sí, y
	   lo segundo que se hace con ella es copiarla a otro sitio. */
	.ipropanel-projects-browser .ipropanel-projects-browser__listado {
		flex: none;
		padding: 0;
		background-color: transparent;
		border-radius: 0;
	}

	/* El listado crece con el contenido y lo absorbe el scroll de la
	   página: la sección `297:4445` mide 1698,65 sumando el alto completo
	   del listado, y un contenedor con scroll propio no hace crecer a su
	   padre (mismo argumento con el que S6.3 descartó scroll interno en
	   el grid). El scrollbar estilizado de base queda sin efecto al no
	   haber overflow. */
	.ipropanel-projects-browser .ipropanel-projects-browser__cards {
		display: flex;
		flex-direction: column;
		gap: 16px;
		width: auto;
		height: auto;
		/* Sin scroll interno no hay barra, así que tampoco el hueco de
		   16px que RD-12 abre en desktop. */
		padding: 0;
		overflow: visible;
	}
}
