/**
 * hachitec portfolio - Grilla (editor + frontend)
 *
 * Los colores de respaldo apuntan primero a la paleta global del sitio
 * (theme.json y colores globales de Astra) y recién después a un valor concreto,
 * así el bloque sigue al sitio en vez de imponerle una estética.
 */

.hachitec-portfolio {
	--hachitec-pf-accent: var(--wp--preset--color--primary, var(--ast-global-color-0, currentColor));
	--hachitec-pf-card-bg: var(--wp--preset--color--base, var(--ast-global-color-5, #ffffff));
	--hachitec-pf-overlay: rgba(14, 14, 18, 0.78);
	--hachitec-pf-overlay-text: #ffffff;
	--hachitec-pf-border: color-mix(in srgb, currentColor 14%, transparent);
	--hachitec-pf-muted: color-mix(in srgb, currentColor 62%, transparent);

	--hachitec-pf-columns: 3;
	--hachitec-pf-gap: 24px;
	--hachitec-pf-card-radius: 0px;
	--hachitec-pf-media-radius: 0px;
	--hachitec-pf-pill-radius: 0px;
	--hachitec-pf-ratio: 16 / 9;
	--hachitec-pf-shadow: none;
	--hachitec-pf-shadow-hover: none;

	--hachitec-pf-hover-speed: 400ms;
	--hachitec-pf-reveal-duration: 700ms;
	/* Si se cambia, hay que cambiar también el valor de `speed` en view.js:
	   es el tiempo tras el cual se limpian las clases del reordenamiento. */
	--hachitec-pf-filter-speed: 450ms;

	--hachitec-pf-ease: cubic-bezier(0.23, 1, 0.32, 1);

	color: inherit;
}

.hachitec-portfolio *,
.hachitec-portfolio *::before,
.hachitec-portfolio *::after {
	box-sizing: border-box;
}

/* Definido acá y no heredado del tema: de esta clase depende que el texto del
   botón de cerrar exista para un lector de pantalla. */
.hachitec-portfolio .screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.hachitec-portfolio__empty {
	margin: 0;
	padding: 2rem 0;
	color: var(--hachitec-pf-muted);
	text-align: center;
}

/* ------------------------------------------------------------------ filtros */

.hachitec-portfolio__filters {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-bottom: calc(var(--hachitec-pf-gap) * 0.9);
}

.hachitec-portfolio__filter {
	margin: 0;
	padding: 0.55em 1.15em;
	border: 1px solid var(--hachitec-pf-border);
	border-radius: var(--hachitec-pf-pill-radius);
	background: transparent;
	color: inherit;
	font: inherit;
	font-size: 0.92em;
	line-height: 1.2;
	cursor: pointer;
	transition:
		color var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease),
		background-color var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease),
		border-color var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease);
}

.hachitec-portfolio__filter:hover {
	border-color: var(--hachitec-pf-accent);
	color: var(--hachitec-pf-accent);
}

.hachitec-portfolio__filter:focus-visible {
	outline: 2px solid var(--hachitec-pf-accent);
	outline-offset: 2px;
}

.hachitec-portfolio__filter.is-active {
	border-color: var(--hachitec-pf-accent);
	background: var(--hachitec-pf-accent);
	color: var(--hachitec-pf-card-bg);
}

/* ------------------------------------------------------------------ grilla */

.hachitec-portfolio__grid {
	display: grid;
	/* `var()` se sustituye antes de que el navegador interprete la regla, así que
	   un entero dentro de repeat() es válido. Lo que NO acepta repeat() es una
	   función matemática: `repeat(min(var(--x), 2), …)` invalida la declaración
	   entera y la grilla se cae a una sola columna. */
	grid-template-columns: repeat(var(--hachitec-pf-columns), minmax(0, 1fr));
	gap: var(--hachitec-pf-gap);
	align-items: stretch;
}

.hachitec-portfolio__card {
	position: relative;
	min-width: 0;
	background: var(--hachitec-pf-card-bg);
	/* Visible en reposo: sin borde la tarjeta flota sobre el fondo y el marco de
	   navegador queda suelto. Con borde se lee como una pieza cerrada. */
	border: 1px solid var(--hachitec-pf-border);
	border-radius: var(--hachitec-pf-card-radius);
	box-shadow: var(--hachitec-pf-shadow);
	/* La elevación del hover se compone en su propia variable en vez de
	   escribirse directo en el transform: así el reveal y el hover no se pisan. */
	--hachitec-pf-card-lift: 0px;
	transform: translate3d(0, var(--hachitec-pf-card-lift), 0);
	transition:
		transform var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease),
		box-shadow var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease),
		border-color var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease);
}

/*
 * Reposo → hover: la tarjeta se levanta, la sombra se profundiza y el borde toma
 * un toque del acento. Las tres juntas son lo que hace que la tarjeta se lea como
 * un objeto que se puede levantar; cada una por separado pasa desapercibida.
 *
 * La elevación entra por `--hachitec-pf-card-lift` y no reescribiendo el
 * `transform`: la animación de entrada anima esa misma propiedad, y si el hover
 * la reescribiera, una tarjeta tocada a mitad del reveal se quedaría sin animar.
 *
 * `--hachitec-pf-shadow-hover` sale del render, calculada a partir de la sombra
 * elegida en el panel. Con "Sin sombra" vale `none`, así que esto no inventa
 * ninguna: la tarjeta solo se levanta.
 *
 * Sin `@media (hover: hover)`, a diferencia del modo en grises. La diferencia es
 * real y no un descuido: lo que necesita ese resguardo es un estado de REPOSO que
 * solo un puntero puede deshacer. Esto es pasajero — en un tap aparece y se va,
 * igual que el acercamiento de la captura y la flecha.
 */
.hachitec-portfolio__card:hover,
.hachitec-portfolio__card:focus-within {
	--hachitec-pf-card-lift: -6px;
	box-shadow: var(--hachitec-pf-shadow-hover);
	border-color: color-mix(in srgb, var(--hachitec-pf-accent) 38%, var(--hachitec-pf-border));
}

/*
 * Grises en reposo, color al pasar el mouse. Es un modo opcional y viene
 * APAGADO: un portfolio en grises se ve apagado justo donde tiene que lucirse, y
 * el trabajo que hay que mostrar es a color.
 *
 * `@media (hover: hover) and (pointer: fine)` y NO un ancho de pantalla: lo que
 * decide si este efecto puede existir no es cuán ancha es la pantalla sino si
 * hay un puntero que pueda pasar por encima. Con un breakpoint por ancho, una
 * tablet o un teléfono en horizontal quedarían grises para siempre, sin forma
 * de revelar la tarjeta.
 *
 * El filtro va en el ENLACE y no en la tarjeta, aunque la tarjeta sería el
 * lugar obvio. Motivo: la animación de entrada "desenfocada" anima `filter` de
 * la tarjeta, y dos reglas sobre la misma propiedad no se combinan — la
 * animación gana mientras corre y su último fotograma queda fijado. La tarjeta
 * aparecería a color y saltaría a gris al terminar. En el enlace las dos cosas
 * conviven porque viven en elementos distintos.
 *
 * `:focus-visible` acompaña al hover para que quien navega con el teclado vea
 * lo mismo al llegar al enlace.
 */
@media (hover: hover) and (pointer: fine) {
	.hachitec-portfolio--desaturate .hachitec-portfolio__link {
		filter: grayscale(1);
	}

	.hachitec-portfolio--desaturate .hachitec-portfolio__card:hover .hachitec-portfolio__link,
	.hachitec-portfolio--desaturate .hachitec-portfolio__link:focus-visible {
		filter: grayscale(0);
	}
}

.hachitec-portfolio__link {
	position: relative;
	display: flex;
	flex-direction: column;
	height: 100%;
	color: inherit;
	text-decoration: none;
	border-radius: inherit;
	overflow: hidden;
	transition: filter var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease);
}

.hachitec-portfolio__link:focus-visible {
	outline: 2px solid var(--hachitec-pf-accent);
	outline-offset: 3px;
}

/* --------------------------------------------- la captura y su marco */

/*
 * La ventana: barra arriba y captura abajo, dentro de una caja con la
 * proporción elegida. La barra tiene alto propio y la captura se queda con lo
 * que sobra, así la tarjeta entera respeta la proporción sin cuentas.
 */
.hachitec-portfolio__media {
	position: relative;
	display: flex;
	flex-direction: column;
	width: 100%;
	aspect-ratio: var(--hachitec-pf-ratio);
	overflow: hidden;
	border-radius: var(--hachitec-pf-media-radius);
	background: var(--hachitec-pf-card-bg);
	/* Sin esto, en Safari la imagen escalada se desborda del redondeo. */
	isolation: isolate;
}

/*
 * Barra de navegador. Decorativa, pero hace dos trabajos reales: una captura
 * suelta se lee como una imagen pegada y dentro de una ventana se lee como un
 * sitio; y libera la esquina superior izquierda de la captura, que es donde
 * TODA web pone su propio logo.
 */
.hachitec-portfolio__chrome {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: 0.6em;
	height: 2.1em;
	padding: 0 0.75em;
	background: color-mix(in srgb, currentColor 7%, var(--hachitec-pf-card-bg));
	border-bottom: 1px solid color-mix(in srgb, currentColor 10%, transparent);
	transition: background-color var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease);
}

.hachitec-portfolio__dots {
	flex: 0 0 auto;
	display: flex;
	gap: 0.3em;
}

.hachitec-portfolio__dots i {
	width: 0.5em;
	height: 0.5em;
	/* Redondos siempre: son los botones de una ventana, no una superficie del
	   bloque. Grises y no rojo/amarillo/verde, para no imitar un sistema
	   operativo concreto ni pelear con la paleta del sitio. */
	border-radius: 50%;
	background: color-mix(in srgb, currentColor 24%, transparent);
	transition: background-color var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease);
}

.hachitec-portfolio__address {
	flex: 1 1 auto;
	min-width: 0;
	padding: 0.2em 0.7em;
	border-radius: var(--hachitec-pf-pill-radius);
	background: color-mix(in srgb, currentColor 7%, var(--hachitec-pf-card-bg));
	color: var(--hachitec-pf-muted);
	font-size: 0.62em;
	line-height: 1.7;
	/* Un dominio largo se corta con puntos suspensivos en vez de empujar la barra. */
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/*
 * La ventana toma foco al pasar el mouse: los puntitos y la barra se encienden.
 * Es el gesto que ya pedía el marco — una ventana activa se ve distinta de una
 * inactiva — y es lo que hace que el hover se lea como entrar al sitio.
 *
 * Los puntitos toman el ACENTO del sitio, no rojo/amarillo/verde: encendidos
 * siguen sin imitar los colores de un sistema operativo concreto, que es el
 * motivo por el que en reposo son grises.
 */
.hachitec-portfolio__card:hover .hachitec-portfolio__chrome,
.hachitec-portfolio__card:focus-within .hachitec-portfolio__chrome {
	background: color-mix(in srgb, currentColor 11%, var(--hachitec-pf-card-bg));
}

.hachitec-portfolio__card:hover .hachitec-portfolio__dots i,
.hachitec-portfolio__card:focus-within .hachitec-portfolio__dots i {
	background: color-mix(in srgb, var(--hachitec-pf-accent) 55%, transparent);
}

.hachitec-portfolio__shot {
	position: relative;
	flex: 1 1 auto;
	/* Sin esto un hijo de flex no baja de su alto de contenido y desborda la caja. */
	min-height: 0;
	overflow: hidden;
	background: color-mix(in srgb, currentColor 8%, transparent);
}

.hachitec-portfolio__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* `top`: una captura de sitio se lee por arriba. Recortar por el centro
	   corta el encabezado, que es lo único que identifica al sitio de un vistazo. */
	object-position: top center;
	transform: scale(1) translate3d(0, 0, 0);
	transition: transform calc(var(--hachitec-pf-hover-speed) * 1.6) var(--hachitec-pf-ease);
	will-change: transform;
}

.hachitec-portfolio--hover-image-zoom .hachitec-portfolio__card:hover .hachitec-portfolio__image {
	transform: scale(1.06);
}

/*
 * Desplazamiento vertical: la captura arranca mostrando el encabezado y al pasar
 * el mouse recorre el sitio hacia abajo. Es el gesto que corresponde a una
 * captura de página, que es alta y angosta, no ancha.
 */
.hachitec-portfolio--hover-image-pan .hachitec-portfolio__image {
	transform: scale(1.06) translate3d(0, 0, 0);
}

.hachitec-portfolio--hover-image-pan .hachitec-portfolio__card:hover .hachitec-portfolio__image {
	transform: scale(1.06) translate3d(0, -6%, 0);
}

/* -------------------------------------------------------- logo del cliente */

.hachitec-portfolio__logo {
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--hachitec-pf-logo-bg, var(--hachitec-pf-card-bg));
}

.hachitec-portfolio__logo img {
	display: block;
	/* `contain` y no `cover`: un logo recortado deja de ser el logo. */
	max-width: 100%;
	max-height: 100%;
	width: auto;
	height: auto;
	object-fit: contain;
}

/*
 * El logo vive en el texto, al lado del nombre, y NO encima de la captura.
 * Encima chocaba siempre: toda web pone su propio logo arriba a la izquierda,
 * así que la chapita quedaba pisando el logo del cliente, duplicado.
 */
.hachitec-portfolio__logo--mark {
	flex: 0 0 auto;
	width: 2.5em;
	height: 2.5em;
	padding: 0.35em;
	border: 1px solid var(--hachitec-pf-border);
	border-radius: var(--hachitec-pf-pill-radius);
}

/*
 * Logo tapando la tarjeta entera. Queda como opción, pero no es la recomendada:
 * funciona con un conjunto de logos parejos sobre fondo neutro —un muro de
 * clientes—, y no con un portfolio donde lo que hay que mostrar es el trabajo.
 *
 * El logo TAPA la captura, no la reemplaza: la captura sigue cargada abajo, así
 * que el cambio es instantáneo y no espera a que cargue nada.
 */
.hachitec-portfolio__logo--full {
	position: absolute;
	inset: 0;
	z-index: 1;
	padding: 12%;
	opacity: 1;
	transition:
		opacity var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease),
		transform var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease);
}

.hachitec-portfolio__card:hover .hachitec-portfolio__logo--full,
.hachitec-portfolio__card .hachitec-portfolio__link:focus-visible .hachitec-portfolio__logo--full {
	opacity: 0;
	/* Un poco de escala al irse: sin esto el fundido se lee como un parpadeo. */
	transform: scale(1.04);
}

.hachitec-portfolio--cover-logo .hachitec-portfolio__card.has-logo .hachitec-portfolio__image {
	transform: scale(1.06);
}

.hachitec-portfolio--cover-logo .hachitec-portfolio__card.has-logo:hover .hachitec-portfolio__image {
	transform: scale(1);
}

/* Velo que oscurece la captura para que el texto encima se lea. */
.hachitec-portfolio__scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(
		to top,
		var(--hachitec-pf-overlay) 0%,
		color-mix(in srgb, var(--hachitec-pf-overlay) 55%, transparent) 42%,
		transparent 78%
	);
	opacity: 1;
	transition: opacity var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease);
	pointer-events: none;
}

.hachitec-portfolio--overlay-hover .hachitec-portfolio__scrim {
	opacity: 0;
}

.hachitec-portfolio--overlay-hover .hachitec-portfolio__card:hover .hachitec-portfolio__scrim,
.hachitec-portfolio--overlay-hover .hachitec-portfolio__link:focus-visible .hachitec-portfolio__scrim {
	opacity: 1;
}

/* ------------------------------------------------------------------ cuerpo */

.hachitec-portfolio__body {
	display: flex;
	align-items: center;
	gap: 0.7em;
	padding: 0.9em 1em 1em;
}

.hachitec-portfolio__names {
	display: flex;
	flex-direction: column;
	gap: 0.1em;
	/* Sin esto, un nombre largo empuja el logo fuera de la tarjeta. */
	min-width: 0;
}

.hachitec-portfolio__eyebrow {
	color: var(--hachitec-pf-accent);
	font-size: 0.7em;
	font-weight: 700;
	letter-spacing: 0.07em;
	line-height: 1.3;
	text-transform: uppercase;
}

.hachitec-portfolio__title {
	display: flex;
	align-items: center;
	gap: 0.35em;
	font-size: 1.1em;
	font-weight: 700;
	line-height: 1.25;
}

.hachitec-portfolio__detail {
	display: block;
	margin-top: 0.25em;
	color: var(--hachitec-pf-muted);
	font-size: 0.85em;
	line-height: 1.45;
}

/*
 * La flecha aparece al pasar el mouse. Es la única señal de "esto se puede
 * abrir" que queda ahora que el dominio se mudó a la barra del marco.
 */
.hachitec-portfolio__arrow {
	flex: 0 0 auto;
	width: 0.7em;
	height: 0.7em;
	color: var(--hachitec-pf-accent);
	opacity: 0;
	transform: translate3d(-0.25em, 0.25em, 0);
	transition:
		opacity var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease),
		transform var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease);
}

.hachitec-portfolio__card:hover .hachitec-portfolio__arrow,
.hachitec-portfolio__link:focus-visible .hachitec-portfolio__arrow {
	opacity: 1;
	transform: none;
}

/* ---------------------------------------------------------------- centrado */

/*
 * Centrar la fila tal como esta —logo al lado del texto— deja el conjunto
 * descentrado a la vista, porque el peso visual del logo tira para un lado y
 * los nombres de largos distintos no arrancan alineados entre tarjetas.
 * Centrado de verdad significa apilar: logo arriba, texto debajo.
 */
.hachitec-portfolio--align-center .hachitec-portfolio__body {
	flex-direction: column;
	align-items: center;
	gap: 0.55em;
	text-align: center;
}

.hachitec-portfolio--align-center .hachitec-portfolio__names {
	align-items: center;
}

.hachitec-portfolio--align-center .hachitec-portfolio__title {
	justify-content: center;
}

/* --------------------------------------------- texto encima de la captura */

.hachitec-portfolio--overlay-hover .hachitec-portfolio__body,
.hachitec-portfolio--overlay-always .hachitec-portfolio__body {
	position: absolute;
	inset: auto 0 0 0;
	z-index: 2;
	padding: 1.1em 1.15em 1.2em;
	color: var(--hachitec-pf-overlay-text);
}

.hachitec-portfolio--overlay-hover .hachitec-portfolio__eyebrow,
.hachitec-portfolio--overlay-always .hachitec-portfolio__eyebrow,
.hachitec-portfolio--overlay-hover .hachitec-portfolio__arrow,
.hachitec-portfolio--overlay-always .hachitec-portfolio__arrow {
	color: color-mix(in srgb, var(--hachitec-pf-overlay-text) 85%, transparent);
}

/* Con el texto encima, la tarjeta mide lo que mide la ventana. */
.hachitec-portfolio--overlay-hover .hachitec-portfolio__media,
.hachitec-portfolio--overlay-always .hachitec-portfolio__media {
	flex: 1 1 auto;
	height: 100%;
}

.hachitec-portfolio--overlay-hover .hachitec-portfolio__body {
	opacity: 0;
	transform: translate3d(0, 14px, 0);
	transition:
		opacity var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease),
		transform var(--hachitec-pf-hover-speed) var(--hachitec-pf-ease);
}

.hachitec-portfolio--overlay-hover .hachitec-portfolio__card:hover .hachitec-portfolio__body,
.hachitec-portfolio--overlay-hover .hachitec-portfolio__link:focus-visible .hachitec-portfolio__body {
	opacity: 1;
	transform: none;
}

/* ------------------------------------------------------- animación de entrada */

/*
 * Las tarjetas salen VISIBLES del servidor. `is-reveal-armed` la pone el JS
 * recién cuando ya confirmó que puede animar: sin esa clase, todo esto no existe
 * y la grilla se ve normal aunque el script nunca llegue a correr.
 */
.hachitec-portfolio__grid.is-reveal-armed .hachitec-portfolio__card {
	opacity: 0;
}

.hachitec-portfolio__grid.is-reveal-armed .hachitec-portfolio__card.is-revealed {
	animation-duration: var(--hachitec-pf-reveal-duration);
	animation-timing-function: var(--hachitec-pf-ease);
	animation-fill-mode: both;
	animation-delay: var(--hachitec-pf-reveal-delay, 0ms);
}

/* Al terminar, el JS limpia la animación. Con `animation-fill-mode: both`
   puesto, el estado final del keyframe le gana al transform del hover y lo
   dejaría muerto. */
.hachitec-portfolio__grid.is-reveal-armed .hachitec-portfolio__card.is-reveal-done {
	animation: none;
	opacity: 1;
}

.hachitec-portfolio--reveal-fade-up .hachitec-portfolio__card.is-revealed {
	animation-name: hachitec-pf-fade-up;
}

.hachitec-portfolio--reveal-scale .hachitec-portfolio__card.is-revealed {
	animation-name: hachitec-pf-scale-in;
}

.hachitec-portfolio--reveal-blur .hachitec-portfolio__card.is-revealed {
	animation-name: hachitec-pf-blur-in;
}

@keyframes hachitec-pf-fade-up {
	from {
		opacity: 0;
		transform: translate3d(0, 26px, 0);
	}
	to {
		opacity: 1;
		transform: translate3d(0, 0, 0);
	}
}

@keyframes hachitec-pf-scale-in {
	from {
		opacity: 0;
		transform: scale(0.92);
	}
	to {
		opacity: 1;
		transform: scale(1);
	}
}

@keyframes hachitec-pf-blur-in {
	from {
		opacity: 0;
		filter: blur(14px);
		transform: scale(1.04);
	}
	to {
		opacity: 1;
		filter: blur(0);
		transform: scale(1);
	}
}

/* ------------------------------------------------------ filtrado animado */

/* Durante el reordenamiento el hover se apaga: si no, una tarjeta que pasa por
   debajo del cursor se eleva en pleno viaje y el salto se nota. */
.hachitec-portfolio__grid.is-filtering .hachitec-portfolio__card {
	pointer-events: none;
}

.hachitec-portfolio__card.is-hidden {
	display: none;
}

.hachitec-portfolio__card.is-moving {
	transition: transform var(--hachitec-pf-filter-speed) var(--hachitec-pf-ease);
	z-index: 1;
}

.hachitec-portfolio__card.is-entering {
	animation: hachitec-pf-filter-in var(--hachitec-pf-filter-speed) var(--hachitec-pf-ease) both;
}

.hachitec-portfolio__card.is-leaving {
	animation: hachitec-pf-filter-out calc(var(--hachitec-pf-filter-speed) * 0.6) var(--hachitec-pf-ease) both;
}

@keyframes hachitec-pf-filter-in {
	from {
		opacity: 0;
		transform: scale(0.9);
	}
	to {
		opacity: 1;
		transform: scale(1);
	}
}

@keyframes hachitec-pf-filter-out {
	from {
		opacity: 1;
		transform: scale(1);
	}
	to {
		opacity: 0;
		transform: scale(0.9);
	}
}

/* --------------------------------------------------------------- responsive */

@media (max-width: 1024px) {
	/*
	 * `auto-fit` y no una cuenta sobre la variable: repeat() no acepta funciones
	 * matemáticas, así que `repeat(min(var(--columnas), 2), …)` es una declaración
	 * inválida que el navegador descarta entera y la grilla se cae a una columna.
	 */
	.hachitec-portfolio__grid {
		grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
	}
}

@media (max-width: 720px) {
	.hachitec-portfolio__grid {
		grid-template-columns: 1fr;
	}

	/*
	 * En pantalla táctil no hay "pasar el mouse": un texto que solo aparece con
	 * hover sería contenido invisible. En celular se muestra siempre.
	 */
	.hachitec-portfolio--overlay-hover .hachitec-portfolio__body {
		opacity: 1;
		transform: none;
		transition: none;
	}

	.hachitec-portfolio--overlay-hover .hachitec-portfolio__scrim {
		opacity: 1;
	}

	/* La barra de filtros se desliza en vez de partirse en varias líneas. */
	.hachitec-portfolio__filters {
		flex-wrap: nowrap;
		overflow-x: auto;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
	}

	.hachitec-portfolio__filters::-webkit-scrollbar {
		display: none;
	}

	.hachitec-portfolio__filter {
		flex: 0 0 auto;
	}
}

/* ------------------------------------------------------ movimiento reducido */

/*
 * Con la preferencia activa no se anima nada, pero TODO se sigue viendo: el
 * cuerpo del overlay pasa a estar siempre visible en vez de quedar escondido
 * detrás de un hover que ya no anima.
 */
@media (prefers-reduced-motion: reduce) {
	.hachitec-portfolio *,
	.hachitec-portfolio *::before,
	.hachitec-portfolio *::after {
		animation-duration: 0.001ms !important;
		animation-delay: 0ms !important;
		transition-duration: 0.001ms !important;
		transition-delay: 0ms !important;
	}

	.hachitec-portfolio--overlay-hover .hachitec-portfolio__body {
		opacity: 1;
		transform: none;
	}

	.hachitec-portfolio--overlay-hover .hachitec-portfolio__scrim {
		opacity: 1;
	}
}
