/*
 * Directory styles for the plugin's listing templates. Moved from the townbuzzmedia
 * theme with the templates they serve; the class names are unchanged.
 *
 * Listing row.
 *
 * Only what core cannot express. Everything else -- color, spacing, border,
 * type -- is a block setting on the pattern or a theme.json token, per the
 * theme's CSS rule. Three things have no block equivalent:
 *
 *   1. a bound field with no value leaves an empty element behind, and there is
 *      no conditional block, so empties are collapsed here;
 *   2. the whole row is a click target, which needs a stretched overlay on the
 *      title link -- block markup cannot nest a Query Loop's contents in one
 *      anchor -- and anything else interactive must then sit above that overlay;
 *   3. the card hover-lift, which the theme lists as sanctioned irreducible CSS.
 */

/* Card hover-lift (sanctioned). position:relative also anchors the overlay. */
.wb-listing {
	position: relative;
	transition: transform 120ms ease, box-shadow 120ms ease;
}

.wb-listing:hover {
	transform: translateY(-2px);
	box-shadow: 0 4px 14px rgb(0 0 0 / 8%);
}

/* Stretch the title link over the whole row. */
.wb-listing .wp-block-post-title a::after {
	position: absolute;
	inset: 0;
	content: "";
	border-radius: inherit;
}

/* Anything genuinely interactive must sit above that overlay. */
.wb-listing a:not(.wp-block-post-title a),
.wb-listing .wp-block-button {
	position: relative;
	z-index: 1;
}

/* Unfilled bindings leave empty elements behind. A bound button with no URL
   renders an anchor with no href, and its wrapper would still hold a gap. */
.wb-listing__meta:empty,
.wb-listing__badge:empty,
.wb-listing .wp-block-post-excerpt:has(.wp-block-post-excerpt__excerpt:empty),
.wb-listing .wp-block-button:not(:has(a[href]:not([href=""]))),
.wb-listing .wp-block-buttons:empty {
	display: none;
}

/*
 * Single listing.
 *
 * Almost every field on a listing is optional -- only 66% have a phone, 28% an
 * email, 29% an Instagram -- and the premium fields are empty on all 605 free
 * listings. Core has no conditional block, so a bound paragraph with no value
 * renders as an empty <p> and a bound button renders an <a> with no href.
 * Collapsing them is the irreducible bit that has to be CSS.
 *
 * Tokens come from theme.json. No hardcoded color or spacing values.
 */

/* An unfilled binding leaves an empty element behind. */
.wb-listing__field:empty,
.wb-listing__badge:empty,
.wb-listing__label:empty {
	display: none;
}

/* A section whose only real content was an empty binding has nothing to show. */
.wb-listing__premium:not(:has(.wb-listing__field:not(:empty))) {
	display: none;
}

/* A bound button with no URL renders an anchor with no href -- not a link.
   Covers the phone link too, which binds its href from townbuzzmedia/tel and
   comes back empty when the listing has no number. */
.wb-listing__card .wp-block-button:not(:has(a[href]:not([href=""]))) {
	display: none;
}

/* When the bound url resolves empty, core drops the whole button and leaves the
   buttons WRAPPER behind. It has no children to match above, but it still takes
   a blockGap slot, so an absent phone opens a phantom gap in the card. */
.wb-listing__card .wp-block-buttons:empty {
	display: none;
}

/* No listing has a description yet, so the body collapses entirely rather
   than leaving a gap under the card. */
.wb-listing__body:not(:has(.wb-listing__field:not(:empty))):not(:has(.wp-block-post-content > *)) {
	display: none;
}

/* Hours arrive as multi-line text from a textarea. */
.wb-listing__hours {
	white-space: pre-line;
}

.wb-listing__badge:not(:empty) {
	align-self: start;
	border: 1px solid currentColor;
	border-radius: 999px;
	padding: 0.15em 0.75em;
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

/*
 * Category cards -- used at BOTH levels of the directory: the sections on
 * /directory/, and a section's categories on /directory/category/<section>/.
 * Both grids are assembled as core blocks by
 * Directory::card_grid() (includes/class-directory.php), because core/categories renders
 * a bare <ul> with no card, grid or image option and a Query Loop has no
 * term-loop at all.
 *
 * One stylesheet for every directory view, because these cards render on two
 * different templates.
 *
 * What is irreducible: making the whole card a click target, and cropping the
 * banner to one shape across separately generated images. A term with no
 * `wb_image` renders a text-only card, which is why nothing here assumes an
 * image is present.
 *
 * Tokens come from theme.json. No hardcoded color or spacing values.
 */

.wb-section-card {
	position: relative;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	height: 100%;
	transition: transform 120ms ease, box-shadow 120ms ease;
}

.wb-section-card:hover {
	transform: translateY(-2px);
	box-shadow: 0 4px 14px rgb(0 0 0 / 8%);
}

/* Eleven separately generated illustrations, normalised to one banner shape. */
.wb-section-card__media {
	margin: 0;
	border-bottom: 1px solid var(--wp--preset--color--line);
}

.wb-section-card__media img {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

.wb-section-card__body {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
}

.wb-section-card h3 {
	margin: 0;
	line-height: 1.2;
}

.wb-section-card h3 a {
	text-decoration: none;
}

/* Whole card is the target. */
.wb-section-card h3 a::after {
	position: absolute;
	inset: 0;
	content: "";
}

.wb-section-card__count {
	margin: 0;
}

/* --- Breadcrumb trail -------------------------------------------------- */

/* Built by Directory::breadcrumbs(). The separator is
   decorative and aria-hidden; the links carry the structure. */
.wb-breadcrumbs__sep {
	opacity: 0.5;
}

.wb-breadcrumbs-trail a {
	text-decoration: none;
}

.wb-breadcrumbs-trail a:hover {
	text-decoration: underline;
}
