/* ===========================================================================
   portfolio-masonry-grid — modern gallery grid with mixed card heights
   ---------------------------------------------------------------------------
   Scope: .vbs-portfolio-masonry-grid
   Depends on: css/tokens.css, css/base.css

   Structure: a filter bar over a three-column bed of cards whose heights are
   set by grid row spans on a fine 2rem row unit, not by their content. Each
   card is a flex column and the media takes the leftover height, so a longer
   title or a heavier preset eats into the crop instead of overflowing the
   card — which is what usually breaks a hand-tuned masonry grid.

   The spans are chosen so all three columns finish on the same row, giving a
   staggered interior and a flat bottom edge. Below 64rem the spans are
   dropped entirely and each card falls back to its own media ratio.

   Contains no literal colour, font, size, weight, radius, shadow or duration.
   ========================================================================= */

/* --- head ----------------------------------------------------------------- */
.vbs-portfolio-masonry-grid__title {
	margin-block-start: 1.25rem;
	max-inline-size: 20ch;
}

.vbs-portfolio-masonry-grid__lead {
	margin-block-start: 1.25rem;
	max-inline-size: var(--vb-max-prose);
}

/* --- filter bar -----------------------------------------------------------
   Chips left, the archive count right, both sitting on a hairline so the bar
   reads as a control strip rather than as more content. */
.vbs-portfolio-masonry-grid__bar {
	margin-block-start: clamp(2rem, 4vw, 3rem);
	padding-block: 1.25rem;
	border-block: var(--vb-border-hair) solid var(--vb-color-rule);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1rem 2rem;
}

.vbs-portfolio-masonry-grid__filter-list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
}

.vbs-portfolio-masonry-grid__filter {
	background-color: var(--vb-panel);
	background-image: var(--vb-panel-image);
	background-blend-mode: var(--vb-panel-blend);
	transition: background-color var(--vb-dur-base) var(--vb-ease-out-soft),
	            border-color var(--vb-dur-base) var(--vb-ease-out-soft),
	            color var(--vb-dur-base) var(--vb-ease-out-soft);
}

.vbs-portfolio-masonry-grid__filter:hover {
	border-color: var(--vb-color-ink);
	color: var(--vb-color-ink);
}

/* The selected filter is the only saturated element in the bar. */
.vbs-portfolio-masonry-grid__filter[aria-current] {
	background-color: var(--vb-color-accent);
	border-color: var(--vb-color-accent);
	color: var(--vb-color-accent-contrast);
	font-weight: var(--vb-weight-strong);
}
.vbs-portfolio-masonry-grid__filter[aria-current]:hover {
	background-color: var(--vb-color-accent-hover);
	border-color: var(--vb-color-accent-hover);
	color: var(--vb-color-accent-contrast);
}

.vbs-portfolio-masonry-grid__count {
	font-size: var(--vb-fs-small);
	line-height: var(--vb-lh-small);
	color: var(--vb-color-mute);
	white-space: nowrap;
}

/* --- the bed --------------------------------------------------------------
   One column, then two on their natural ratios, then three on row spans. */
.vbs-portfolio-masonry-grid__grid {
	margin-block-start: clamp(1.75rem, 3.5vw, 2.5rem);
	display: grid;
	gap: 1.25rem;
}

@media (min-width: 40rem) {
	.vbs-portfolio-masonry-grid__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 64rem) {
	.vbs-portfolio-masonry-grid__grid {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		/* Fine row unit: the span numbers below are the whole layout. */
		grid-auto-rows: 2rem;
	}

	/* Column 1: 12 + 8 = 20 rows. Column 2: 8 + 12. Column 3: 10 + 10.
	   Every column lands on row 21, so the block closes square. */
	.vbs-portfolio-masonry-grid__cell--s1 { grid-column: 1; grid-row: 1 / span 12; }
	.vbs-portfolio-masonry-grid__cell--s2 { grid-column: 2; grid-row: 1 / span 8; }
	.vbs-portfolio-masonry-grid__cell--s3 { grid-column: 3; grid-row: 1 / span 10; }
	.vbs-portfolio-masonry-grid__cell--s4 { grid-column: 1; grid-row: 13 / span 8; }
	.vbs-portfolio-masonry-grid__cell--s5 { grid-column: 2; grid-row: 9 / span 12; }
	.vbs-portfolio-masonry-grid__cell--s6 { grid-column: 3; grid-row: 11 / span 10; }
}

/* --- card ----------------------------------------------------------------- */
.vbs-portfolio-masonry-grid__cell { display: flex; }

.vbs-portfolio-masonry-grid__card {
	position: relative;
	isolation: isolate;
	inline-size: 100%;
	display: flex;
	flex-direction: column;
	background-color: var(--vb-panel);
	background-image: var(--vb-panel-image);
	background-blend-mode: var(--vb-panel-blend);
	border: var(--vb-border-hair) solid var(--vb-color-rule);
	border-radius: var(--vb-radius-card);
	overflow: hidden;
	transition: transform var(--vb-dur-base) var(--vb-ease-out-soft),
	            box-shadow var(--vb-dur-base) var(--vb-ease-out-soft),
	            border-color var(--vb-dur-base) var(--vb-ease-out-soft);
}

/* The card already draws the outer corner, so the crop squares off inside it
   — two nested radii on the same corner always read as a mistake. */
.vbs-portfolio-masonry-grid__media {
	border-radius: 0;
	flex: none;
}

/* With a row span driving the height, the crop absorbs whatever the body
   does not need. min-block-size keeps a two-line title from eating it. */
@media (min-width: 64rem) {
	.vbs-portfolio-masonry-grid__media {
		aspect-ratio: auto;
		flex: 1 1 auto;
		min-block-size: 7rem;
	}
}

.vbs-portfolio-masonry-grid__body {
	flex: none;
	padding: clamp(1rem, 1.6vw, 1.375rem);
	display: flex;
	flex-direction: column;
	align-items: start;
	gap: 0.625rem;
}

.vbs-portfolio-masonry-grid__cat {
	background-color: var(--vb-panel-2);
	background-image: var(--vb-panel-image);
	background-blend-mode: var(--vb-panel-blend);
}

.vbs-portfolio-masonry-grid__name {
	transition: color var(--vb-dur-base) var(--vb-ease-out-soft);
}

/* Stretched hit area: the title anchor is the only link, and its ::after
   covers the whole card so the entire tile is clickable without nesting a
   second <a> inside the overlay. */
.vbs-portfolio-masonry-grid__link::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

.vbs-portfolio-masonry-grid__meta {
	font-size: var(--vb-fs-small);
	line-height: var(--vb-lh-small);
	color: var(--vb-color-mute);
	text-wrap: pretty;
}

/* --- hover overlay --------------------------------------------------------
   A scrim mixed from the ink role, so it darkens a light brand and lightens
   a dark one. Decorative and pointer-transparent — the stretched link under
   it stays clickable, and screen readers never meet a duplicate label. */
.vbs-portfolio-masonry-grid__overlay {
	position: absolute;
	inset: 0;
	z-index: 2;
	display: grid;
	place-items: center;
	pointer-events: none;
	background-color: color-mix(in srgb, var(--vb-color-ink) 74%, transparent);
	opacity: 0;
	transition: opacity var(--vb-dur-base) var(--vb-ease-out-soft);
}

.vbs-portfolio-masonry-grid__view {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	padding: 0.7em 1.2em;
	border: var(--vb-border-hair) solid var(--vb-color-paper);
	border-radius: var(--vb-radius-btn);
	color: var(--vb-color-paper);
	font-size: var(--vb-fs-small);
	font-weight: var(--vb-weight-strong);
	line-height: 1;
	transform: translateY(0.5rem);
	transition: transform var(--vb-dur-base) var(--vb-ease-out-soft);
}

.vbs-portfolio-masonry-grid__card:hover,
.vbs-portfolio-masonry-grid__card:focus-within {
	transform: translateY(-0.25rem);
	border-color: var(--vb-color-ink);
	box-shadow: var(--vb-shadow-card-hover);
}

.vbs-portfolio-masonry-grid__card:hover .vbs-portfolio-masonry-grid__overlay,
.vbs-portfolio-masonry-grid__card:focus-within .vbs-portfolio-masonry-grid__overlay {
	opacity: 1;
}

.vbs-portfolio-masonry-grid__card:hover .vbs-portfolio-masonry-grid__view,
.vbs-portfolio-masonry-grid__card:focus-within .vbs-portfolio-masonry-grid__view {
	transform: translateY(0);
}

.vbs-portfolio-masonry-grid__card:hover .vbs-portfolio-masonry-grid__name,
.vbs-portfolio-masonry-grid__card:focus-within .vbs-portfolio-masonry-grid__name {
	color: var(--vb-chroma-ink);
}

/* --- footer --------------------------------------------------------------- */
.vbs-portfolio-masonry-grid__more {
	margin-block-start: clamp(2rem, 4vw, 3rem);
	display: flex;
	justify-content: center;
}

/* Paired and staggered layouts remove fixed masonry row spans. Text length
   can grow the row naturally, while the media retains a useful crop. */
.vbs-portfolio-masonry-grid[data-vb-compose] .vbs-portfolio-masonry-grid__grid { gap: var(--vb-section-gap); }
.vbs-portfolio-masonry-grid[data-vb-compose] .vbs-portfolio-masonry-grid__body { padding: var(--vb-card-padding); }
.vbs-portfolio-masonry-grid[data-vb-layout="paired"] .vbs-portfolio-masonry-grid__grid,
.vbs-portfolio-masonry-grid[data-vb-layout="staggered"] .vbs-portfolio-masonry-grid__grid { grid-auto-rows: auto; }
.vbs-portfolio-masonry-grid[data-vb-layout="paired"] .vbs-portfolio-masonry-grid__cell,
.vbs-portfolio-masonry-grid[data-vb-layout="staggered"] .vbs-portfolio-masonry-grid__cell { grid-area: auto; }
.vbs-portfolio-masonry-grid[data-vb-layout="paired"] .vbs-portfolio-masonry-grid__media,
.vbs-portfolio-masonry-grid[data-vb-layout="staggered"] .vbs-portfolio-masonry-grid__media { aspect-ratio: 4 / 3; flex: none; }
@media (min-width: 40rem) {
 .vbs-portfolio-masonry-grid[data-vb-layout="paired"] .vbs-portfolio-masonry-grid__grid,
 .vbs-portfolio-masonry-grid[data-vb-layout="staggered"] .vbs-portfolio-masonry-grid__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
 .vbs-portfolio-masonry-grid[data-vb-layout="staggered"] .vbs-portfolio-masonry-grid__cell:nth-child(even) { padding-block-start: calc(var(--vb-section-gap) * 2); }
 .vbs-portfolio-masonry-grid[data-vb-layout="staggered"] .vbs-portfolio-masonry-grid__media { aspect-ratio: 4 / 5; }
}
