/*!
 * PetMap Directory — the [petmap_directory] component.
 *
 * Loaded only on pages that render the component (see Front\Assets).
 *
 * Every value here reads a --pmd-* token emitted by Front\DesignSystem. The
 * three exceptions are the ones the design itself writes as literals: the six
 * thumbnail gradients, and the two tag tints, which are the success and warning
 * tokens at low alpha. Both tags declare the design's literal first and the
 * token-derived color-mix() second, the same fallback idiom the design uses for
 * --pmd-color-primary-soft — an older browser gets the literal, a current one
 * gets a tint that follows the site's palette.
 *
 * Layout is mobile-first: one column stacked, then the design's three-column
 * split from 1024px up, which is the width the 220 / 400 / rest grid was drawn
 * for. Everything the narrow layout needs is in the base; the media query only
 * ever adds the desktop behaviour on top.
 *
 * Below the split the phone shows one result column at a time. Which one is a
 * server decision carried in `pmd_view`, and the component root wears it as
 * `pmd-view-list` / `pmd-view-map`; both columns are always in the markup, so
 * the rules that hide one of them live in the base and are undone at 1024px.
 *
 * Every control the narrow layout offers is at least 44px on its shortest
 * side. The design's own note puts the quick-filter chips at 34px; that is a
 * drawing measurement, not a target a thumb can hit, so the chips are 44px
 * here and the row scrolls sideways to make room. The smaller sizes the design
 * draws are restored above the breakpoint, where the pointer is a mouse.
 *
 * @package PetMapDirectory
 */

.pmd-directory {
	display: flex;
	flex-direction: column;
	/*
	 * `clip` rather than `hidden` wherever it is understood. Both clip the
	 * children to the rounded corner, but `hidden` also makes this a scroll
	 * container, and a scroll container between the floating button and the
	 * viewport is what would stop the button floating. The `hidden` line stays
	 * as the fallback for a browser that has not met `clip` — the same
	 * progressive-declaration idiom the tags below use for color-mix().
	 */
	overflow: hidden;
	overflow: clip;
	color: var(--pmd-color-text);
	font-family: var(--pmd-font-sans, inherit);
	text-align: left;
	background: var(--pmd-color-surface);
	border: 1px solid var(--pmd-color-border);
	border-radius: var(--pmd-radius-lg);
}

/*
 * One result column at a time below the split.
 *
 * Both are in the markup either way: above 1024px the design shows the cards
 * and the map at once, and the default view is the list, so hiding by class
 * here rather than dropping a column on the server is what keeps the map on
 * every desktop page load.
 */
.pmd-view-map .pmd-dir-cards,
.pmd-view-list .pmd-dir-map {
	display: none;
}

.pmd-directory .pmd-ico {
	display: block;
	flex: none;
}

.pmd-visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* ── Results bar ─────────────────────────────────────────────── */

.pmd-dir-bar {
	display: flex;
	flex: none;
	align-items: center;
	justify-content: space-between;
	gap: var(--pmd-space-4);
	padding: var(--pmd-space-3) var(--pmd-space-5);
	background: var(--pmd-color-surface);
	border-bottom: 1px solid var(--pmd-color-border);
}

.pmd-dir-bar-count {
	margin: 0;
	color: var(--pmd-color-text-muted);
	font-size: var(--pmd-text-sm);
}

.pmd-dir-bar-count strong {
	color: var(--pmd-color-text);
	font-weight: var(--pmd-weight-semibold);
}

/* ── View toggle (narrow layout only) ────────────────────────── */

/*
 * Two links dressed as a segmented control. The design draws it in the bar at
 * every width; above the split it is hidden, because there both result columns
 * are on screen at once and a switch between them would mean nothing.
 */
.pmd-viewseg {
	display: flex;
	flex: none;
	gap: 2px;
	padding: 2px;
	background: var(--pmd-color-surface-alt);
	border: 1px solid var(--pmd-color-border);
	border-radius: var(--pmd-radius-md);
}

.pmd-viewseg-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 5px;
	min-height: 44px;
	padding: 0 12px;
	color: var(--pmd-color-text-muted);
	font-size: 13px;
	font-weight: var(--pmd-weight-medium);
	text-decoration: none;
	border-radius: 6px;
	transition: all var(--pmd-duration-fast) var(--pmd-ease-out);
}

.pmd-viewseg-btn.is-active {
	color: var(--pmd-color-text);
	background: var(--pmd-color-surface);
	box-shadow: var(--pmd-shadow-sm);
}

.pmd-viewseg-btn:focus-visible {
	outline: 2px solid var(--pmd-color-primary);
	outline-offset: 2px;
}

/* ── Split ───────────────────────────────────────────────────── */

.pmd-dir-split {
	display: grid;
	/*
	 * minmax(0, 1fr), never a bare 1fr: a grid item's default
	 * `min-width: auto` refuses to shrink below its own min-content, and
	 * the cards' min-content is around 392px (a 92px thumb plus a title's
	 * longest word). In a 350px column on a phone that pushed the filters
	 * and the card list straight through the widget's right edge.
	 */
	grid-template-columns: minmax(0, 1fr);
	flex: 1;
	min-height: 0;
}

/* ── Column 1: filters ───────────────────────────────────────── */

.pmd-dir-filters {
	display: flex;
	flex-direction: column;
	gap: var(--pmd-space-5);
	margin: 0;
	padding: var(--pmd-space-4);
	background: var(--pmd-color-surface);
	border-bottom: 1px solid var(--pmd-color-border);
}

/*
 * The filter column as a native disclosure.
 *
 * <details> rather than a class and a listener: it opens and closes with no
 * JavaScript, reaches the keyboard with no ARIA, and degrades in a browser
 * that has never heard of it to the filters rendered expanded — which is
 * exactly the state this replaces.
 *
 * It ships closed, which is the narrow-width state. The server cannot know the
 * viewport, so the desktop block below is what forces it open again.
 */
.pmd-fsummary {
	display: flex;
	align-items: center;
	gap: var(--pmd-space-2);
	min-height: 44px;
	padding: 0 var(--pmd-space-3);
	color: var(--pmd-color-text);
	font-size: var(--pmd-text-sm);
	font-weight: var(--pmd-weight-medium);
	background: var(--pmd-color-surface);
	border: 1px solid var(--pmd-color-border-strong);
	border-radius: var(--pmd-radius-md);
	cursor: pointer;
	list-style: none;
}

/* Safari still draws the disclosure triangle through this pseudo-element. */
.pmd-fsummary::-webkit-details-marker {
	display: none;
}

.pmd-fsummary:focus-visible {
	outline: 2px solid var(--pmd-color-primary);
	outline-offset: 2px;
}

.pmd-fsummary-label {
	flex: 1;
}

/*
 * How many filters are narrowing the listing, so a collapsed column still says
 * that something is on. The number is aria-hidden and a visually hidden phrase
 * beside it carries the same count in words; a screen reader announcing a bare
 * "3" on a summary says nothing at all.
 */
.pmd-fbadge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 20px;
	height: 20px;
	padding: 0 6px;
	color: var(--pmd-color-on-primary);
	font-size: 11px;
	font-weight: var(--pmd-weight-bold);
	background: var(--pmd-color-primary);
	border-radius: var(--pmd-radius-pill);
}

.pmd-fsummary-mark {
	color: var(--pmd-color-text-muted);
	transition: transform var(--pmd-duration-fast) var(--pmd-ease-out);
}

.pmd-fdisclosure[open] .pmd-fsummary-mark {
	transform: rotate(180deg);
}

.pmd-fbody {
	display: flex;
	flex-direction: column;
	gap: var(--pmd-space-5);
	padding-top: var(--pmd-space-4);
}

.pmd-ftitle {
	margin: 0 0 var(--pmd-space-2);
	color: var(--pmd-color-text-subtle);
	font-size: 11px;
	font-weight: var(--pmd-weight-semibold);
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

.pmd-select-wrap {
	position: relative;
}

/*
 * Centred rather than offset from the top: the field is 44px on a phone and
 * 36px above the split, and one rule has to sit the chevron in both.
 */
.pmd-select-wrap .pmd-ico {
	position: absolute;
	top: 50%;
	right: 10px;
	transform: translateY(-50%);
	color: var(--pmd-color-text-muted);
	pointer-events: none;
}

.pmd-fselect {
	width: 100%;
	height: 44px;
	padding: 0 32px 0 10px;
	color: var(--pmd-color-text);
	font-family: var(--pmd-font-sans, inherit);
	font-size: var(--pmd-text-sm);
	background: var(--pmd-color-surface);
	border: 1px solid var(--pmd-color-border-strong);
	border-radius: var(--pmd-radius-md);
	appearance: none;
	-webkit-appearance: none;
}

/*
 * The radio and checkbox behind every chip. Hidden from sight, not from the
 * keyboard or a screen reader: the label is the control's own label, so
 * clicking it toggles the input and tabbing still reaches it. That is what
 * makes the filter column work with JavaScript switched off.
 */
.pmd-choice {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
}

/*
 * The chips scroll sideways rather than wrapping.
 *
 * Four 44px chips wrapped onto three rows is a third of a phone screen spent
 * on filters nobody has chosen yet. Scrolled, the row keeps its height and the
 * chips past the edge are one swipe away.
 *
 * `overflow: auto hidden` would clip the 2px focus ring on a chip, hence the
 * vertical padding: the ring needs somewhere to be drawn.
 */
.pmd-chips {
	display: flex;
	flex-wrap: nowrap;
	gap: var(--pmd-space-2);
	padding-block: 3px;
	overflow: auto hidden;
	scrollbar-width: thin;
	overscroll-behavior-x: contain;
	-webkit-overflow-scrolling: touch;
}

.pmd-chip {
	/*
	 * THEME LEAK GUARD — an explicit width, on a control that is a <label>.
	 *
	 * Themes commonly ship `label { width: 100% }` for form layout (this
	 * site's does), and nothing in this rule contradicted it, so every
	 * filter chip stretched to the full width of its row and the row
	 * overflowed its container. A single class beats a bare element
	 * selector, so declaring the width here is all it takes — but it has to
	 * be declared. ThemeSpecificityGuardTest keeps this from being dropped.
	 */
	width: auto;
	max-width: 100%;
	display: flex;
	flex: none;
	align-items: center;
	gap: 5px;
	height: 44px;
	padding: 0 14px;
	color: var(--pmd-color-text-muted);
	font-family: inherit;
	font-size: 13px;
	background: var(--pmd-color-surface);
	border: 1px solid var(--pmd-color-border);
	border-radius: var(--pmd-radius-pill);
	cursor: pointer;
	transition: all var(--pmd-duration-fast) var(--pmd-ease-out);
}

.pmd-choice:checked + .pmd-chip,
.pmd-chip.is-active {
	color: var(--pmd-color-primary);
	font-weight: var(--pmd-weight-medium);
	background: var(--pmd-color-primary-soft);
	border-color: var(--pmd-color-primary);
}

.pmd-sort {
	display: flex;
	flex-direction: column;
	gap: var(--pmd-space-1);
}

.pmd-sort-btn {
	width: auto;
	max-width: 100%;
	display: flex;
	align-items: center;
	gap: 9px;
	min-height: 44px;
	padding: 0 10px;
	color: var(--pmd-color-text-muted);
	font-family: inherit;
	font-size: 13px;
	text-align: left;
	background: var(--pmd-color-surface);
	border: 1px solid transparent;
	border-radius: var(--pmd-radius-md);
	cursor: pointer;
	transition: all var(--pmd-duration-fast) var(--pmd-ease-out);
}

.pmd-choice:checked + .pmd-sort-btn,
.pmd-sort-btn.is-active {
	color: var(--pmd-color-primary);
	font-weight: var(--pmd-weight-medium);
	background: var(--pmd-color-primary-soft);
	border-color: var(--pmd-color-primary);
}

.pmd-choice:focus-visible + .pmd-chip,
.pmd-choice:focus-visible + .pmd-sort-btn {
	outline: 2px solid var(--pmd-color-primary);
	outline-offset: 2px;
}

.pmd-dir-foot {
	display: flex;
	align-items: center;
	gap: var(--pmd-space-3);
	margin-top: auto;
}

.pmd-apply {
	min-height: 44px;
	padding: 0 18px;
	color: var(--pmd-color-on-primary);
	font-family: var(--pmd-font-sans, inherit);
	font-size: 13px;
	font-weight: var(--pmd-weight-medium);
	background: var(--pmd-color-primary);
	border: 1px solid var(--pmd-color-primary);
	border-radius: var(--pmd-radius-md);
	cursor: pointer;
}

.pmd-apply:hover {
	background: var(--pmd-color-primary-hover);
	border-color: var(--pmd-color-primary-hover);
}

.pmd-clear,
a.pmd-clear:link,
a.pmd-clear:visited {
	display: flex;
	align-items: center;
	gap: 6px;
	min-height: 44px;
	padding: 0 var(--pmd-space-2);
	color: var(--pmd-color-text-subtle);
	font-size: 13px;
	text-decoration: none;
}

/* ── Column 2: cards ─────────────────────────────────────────── */

/*
 * No `overflow-y` here: the column only has a height to scroll within above
 * the split, so the scroll container is declared there. Below it the list is
 * part of the page, and a scroll container around it would pin the floating
 * button to the bottom of the list instead of to the bottom of the screen.
 *
 * The extra bottom padding is the room the floating button needs. Without it
 * the button would come to rest over the last card's content at the end of
 * the list, which is the one card a visitor scrolled all the way down to read.
 */
.pmd-dir-cards {
	display: flex;
	flex-direction: column;
	gap: var(--pmd-space-4);
	padding: var(--pmd-space-4) var(--pmd-space-4) var(--pmd-space-7);
	background: var(--pmd-color-surface-alt);
}

.pmd-card {
	position: relative;
	display: flex;
	flex: none;
	flex-direction: column;
	overflow: hidden;
	background: var(--pmd-color-surface);
	border: 1px solid var(--pmd-color-border);
	border-radius: var(--pmd-radius-lg);
	transition:
		box-shadow var(--pmd-duration-fast) var(--pmd-ease-out),
		border-color var(--pmd-duration-fast) var(--pmd-ease-out);
}

.pmd-card:hover {
	box-shadow: var(--pmd-shadow-md);
}

/*
 * Set by front.js when this card's pin is the active one — from a click on
 * the card itself, or from the matching pin on the map. Same treatment the
 * map gives its own active pin (a primary-colored halo), so the two controls
 * read as one selection rather than two independent states that happen to
 * agree.
 */
.pmd-card.is-active {
	border-color: var(--pmd-color-primary);
	box-shadow: var(--pmd-shadow-md);
}

.pmd-card-row {
	display: flex;
	gap: var(--pmd-space-3);
	padding: 10px;
}

/*
 * Tinted with the brand: the colour a photo loads over, and — for a place
 * with none — the ground of its category tile below.
 */
.pmd-card-thumb {
	position: relative;
	width: 92px;
	height: 92px;
	flex: none;
	overflow: hidden;
	background: var(--pmd-color-primary-soft);
	border-radius: var(--pmd-radius-md);
}

/*
 * A place without a photo: its category's pin icon on the tint, so the
 * listing says "vet", "park", "restaurant" at a glance (templates/directory/
 * card.php; Front\Directory picks the icon). The icon is a bundled preset
 * painted through a mask, so it takes the accent like the pins on the map.
 * The map's place card reuses both classes on its media strip (front.js's
 * buildCategoryTile()).
 */
.pmd-card-tile {
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: inset 0 0 0 1px rgba(15, 23, 42, 0.04);
}

.pmd-card-tile-ico {
	display: block;
	width: 42%;
	height: 42%;
	background-color: var(--pmd-color-accent, var(--pmd-color-primary));
	-webkit-mask-image: var(--pmd-icon);
	mask-image: var(--pmd-icon);
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-size: contain;
	mask-size: contain;
}

.pmd-card-img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/*
 * Six gradients, picked from the post ID so a place keeps its colour — the
 * place page's empty gallery still uses them; the directory card and the
 * map's place card draw the category tile instead. Literal values by design:
 * a catalogue of places with no photos still has to read as a catalogue, and
 * a row of identical grey squares does not.
 */
.pmd-thumb-1 { background: linear-gradient(135deg, #fde68a 0%, #f59e0b 100%); }
.pmd-thumb-2 { background: linear-gradient(135deg, #bbf7d0 0%, #10b981 100%); }
.pmd-thumb-3 { background: linear-gradient(135deg, #fbcfe8 0%, #ec4899 100%); }
.pmd-thumb-4 { background: linear-gradient(135deg, #bfdbfe 0%, #3b82f6 100%); }
.pmd-thumb-5 { background: linear-gradient(135deg, #ddd6fe 0%, #7c3aed 100%); }
.pmd-thumb-6 { background: linear-gradient(135deg, #fed7aa 0%, #ea580c 100%); }

.pmd-card-body {
	display: flex;
	flex: 1;
	flex-direction: column;
	min-width: 0;
}

.pmd-card-top {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--pmd-space-2);
}

.pmd-card-head {
	min-width: 0;
}

/*
 * An explicit colour, not an inherited one: the title is an <h3>, and themes
 * paint headings by tag (`body h3 { color: … }`), which beats inheritance and
 * put dark titles on a dark card on a real site. Reading the token also lets
 * the Elementor widget's text colour reach the title; the link below inherits
 * from here.
 */
/*
 * THEME LEAK GUARD — why this selector carries its component root.
 *
 * A heading inside a PetMap component must take this design system's type
 * scale, not the host theme's. Themes routinely ship a rule like
 * `body.page h3 { font-size: 26px }` (this site's does), and that is
 * (0,1,2) — one class, two elements — so it beats a bare
 * `.pmd-card-title` (0,1,0) and the card titles on any WordPress
 * *page* rendered at 26px while the same card on a single place rendered
 * at 15px. Prefixing the component root makes this (0,2,x): two classes
 * always win over one, whatever elements the theme's selector names.
 *
 * Every rule that styles a PetMap heading is scoped this way, and
 * ThemeSpecificityGuardTest fails the build if a new one is not.
 */
.pmd-card .pmd-card-title {
	margin: 0;
	color: var(--pmd-color-text);
	font-family: var(--pmd-font-display, var(--pmd-font-sans, inherit));
	font-size: 15px;
	font-weight: var(--pmd-weight-semibold);
	line-height: 1.3;
}

.pmd-card .pmd-card-title a {
	color: inherit;
	text-decoration: none;
}

/*
 * The title link covers the whole card.
 *
 * A one-line title is roughly 20px tall; on a phone that is a target you miss.
 * Stretching the same link over the card makes the tappable area the card's
 * own 112px, without adding a second link to the same place for a screen
 * reader to read out twice.
 */
.pmd-card .pmd-card-title a::after {
	position: absolute;
	inset: 0;
	content: "";
}

.pmd-card .pmd-card-title a:hover {
	color: var(--pmd-color-primary);
}

.pmd-card .pmd-card-title a:focus-visible {
	outline: 2px solid var(--pmd-color-primary);
	outline-offset: 2px;
}

.pmd-card-cats {
	margin: 2px 0 0;
	color: var(--pmd-color-text-muted);
	font-size: var(--pmd-text-xs);
}

.pmd-card-rating {
	display: flex;
	flex: none;
	align-items: center;
	gap: 4px;
	color: var(--pmd-color-text);
	font-size: 13px;
	font-weight: var(--pmd-weight-medium);
}

.pmd-card-rating .pmd-ico {
	color: var(--pmd-color-warning);
}

.pmd-card-rating .cnt {
	color: var(--pmd-color-text-subtle);
	font-weight: var(--pmd-weight-regular);
}

.pmd-card-foot {
	display: flex;
	align-items: center;
	gap: 7px;
	min-width: 0;
	margin-top: auto;
	padding-top: var(--pmd-space-2);
	color: var(--pmd-color-text-subtle);
	font-size: var(--pmd-text-xs);
}

/*
 * Front\PlacePage's "nearby places" is the one caller that adds
 * distance_label to a card (see card.php's own docblock) — a short,
 * two-token value ("1,2 km") that must read as one measurement, never
 * break after the comma. `.pmd-card-foot` is a flex row with no
 * `flex-wrap`, so its last child still shrinks under a narrow card and, at
 * the default `white-space: normal`, wraps at that inner space; nowrap
 * keeps it one line at any card width the nearby grid produces.
 * margin-left: auto reads as "distance, at a glance, on the right" rather
 * than crowding into the tag/locality group on the left.
 */
/*
 * The locality is the only part of this row that can be arbitrarily long, so
 * it is the only part allowed to shrink: the chip and the distance keep
 * their size and the place name is truncated with an ellipsis instead of
 * folding across three lines in a phone-width card.
 */
.pmd-card-where {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	min-width: 0;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

.pmd-card-where .pmd-ico {
	flex: 0 0 auto;
}

.pmd-card-distance {
	margin-left: auto;
	padding-left: var(--pmd-space-2);
	white-space: nowrap;
}

.pmd-tag {
	display: inline-flex;
	align-items: center;
	padding: 2px 7px;
	color: #0b6b4f;
	color: color-mix(in srgb, var(--pmd-color-success) 72%, #000);
	font-size: 11px;
	font-weight: var(--pmd-weight-medium);
	background: rgba(16, 185, 129, 0.12);
	background: color-mix(in srgb, var(--pmd-color-success) 12%, transparent);
	border-radius: var(--pmd-radius-sm);
}

.pmd-tag.is-closing {
	color: #9a5b06;
	color: color-mix(in srgb, var(--pmd-color-warning) 72%, #000);
	background: rgba(245, 158, 11, 0.14);
	background: color-mix(in srgb, var(--pmd-color-warning) 14%, transparent);
}

/* ── Empty state ─────────────────────────────────────────────── */

.pmd-empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 9px;
	padding: var(--pmd-space-5) var(--pmd-space-4);
	color: var(--pmd-color-text-subtle);
	text-align: center;
	background: var(--pmd-color-surface);
	border: 1px dashed var(--pmd-color-border-strong);
	border-radius: var(--pmd-radius-lg);
}

.pmd-empty h4 {
	margin: 0;
	color: var(--pmd-color-text);
	font-size: var(--pmd-text-sm);
	font-weight: var(--pmd-weight-semibold);
}

.pmd-empty p {
	margin: 0;
	color: var(--pmd-color-text-muted);
	font-size: var(--pmd-text-xs);
	line-height: var(--pmd-leading-normal);
}

.pmd-btn-ghost,
a.pmd-btn-ghost:link,
a.pmd-btn-ghost:visited {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	height: 32px;
	padding: 0 13px;
	color: var(--pmd-color-primary);
	font-family: inherit;
	font-size: 13px;
	font-weight: var(--pmd-weight-medium);
	text-decoration: none;
	background: var(--pmd-color-primary-soft);
	border: 1px solid transparent;
	border-radius: var(--pmd-radius-md);
	cursor: pointer;
}

/* ── Floating action button (narrow layout only) ─────────────── */

/*
 * The one way from the list to the map that does not mean scrolling back to
 * the bar. A link, so it works with JavaScript off, and sticky rather than
 * fixed, so it belongs to the listing: it floats above the cards while they
 * are on screen and leaves with them, instead of hovering over whatever else
 * the page happens to be showing.
 *
 * Sticky also means it keeps a place in the flow, after the last card — which
 * is what stops it ever coming to rest on top of one.
 */
.pmd-fab,
a.pmd-fab:link,
a.pmd-fab:visited {
	position: sticky;
	bottom: var(--pmd-space-4);
	z-index: var(--pmd-z-sticky);
	display: inline-flex;
	flex: none;
	align-self: center;
	align-items: center;
	gap: var(--pmd-space-2);
	min-height: 48px;
	margin-top: var(--pmd-space-2);
	padding: 0 22px;
	color: var(--pmd-color-surface);
	font-size: var(--pmd-text-sm);
	font-weight: var(--pmd-weight-semibold);
	text-decoration: none;
	background: var(--pmd-color-text);
	border-radius: var(--pmd-radius-pill);
	box-shadow: var(--pmd-shadow-lg);
}

.pmd-fab:focus-visible {
	outline: 2px solid var(--pmd-color-primary);
	outline-offset: 3px;
}

/* ── Column 3: map ───────────────────────────────────────────── */

.pmd-dir-map {
	position: relative;
	min-height: 320px;
	overflow: hidden;
	background: var(--pmd-color-surface-alt);
}

/*
 * On the map view the map is the result column, not a strip under the cards,
 * so it takes the screen the list would have had.
 */
.pmd-view-map .pmd-dir-map {
	min-height: 70vh;
}

/*
 * Overrides assets/css/front.css, which gives every .petmap-map a 300px
 * min-height and a grey plate. Inside the directory the container fills its
 * column instead, and Leaflet paints the plate itself.
 */
.pmd-dir-map .petmap-map {
	position: absolute;
	inset: 0;
	width: auto;
	min-height: 0;
	background: transparent;
}

/* ── Map markers & popup (Front\Directory's listing-driven feed) ── */

/*
 * The paw-pin marker. Geometry lifted from templates/mock/directory.php;
 * assets/js/front/front.js builds the same divIcon and explains there why
 * the SVG's fill is a literal hex rather than a var() — that reasoning
 * belongs to the markup, not the stylesheet, so it is not repeated here.
 */
.pmd-pin-wrap {
	background: none;
	border: 0;
}

.pmd-pin {
	display: block;
	cursor: pointer;
	filter: drop-shadow(0 3px 5px rgba(15, 23, 42, 0.35));
}

.pmd-pin.is-active {
	filter: drop-shadow(0 4px 7px rgba(15, 23, 42, 0.42)) brightness(0.92);
}

/*
 * The pin grows from its tip as one piece — the SVG and the category glyph
 * over it together (.pmd-pin-icon below), so the glyph never slides out of
 * the head. Hovered or pointed at from a list (front.js's `is-highlighted`,
 * the explorer's hovered result) it lifts a little; selected
 * (aria-pressed, set by front.js) it grows and wears a soft ring, and both
 * come to the front of their neighbours.
 */
.pmd-pin-wrap:hover .pmd-pin-icon,
.pmd-pin-wrap.is-highlighted .pmd-pin-icon {
	transform: scale(1.1);
}

.pmd-pin-wrap[aria-pressed="true"] .pmd-pin-icon {
	transform: scale(1.22);
}

.pmd-pin-wrap.is-highlighted,
.pmd-pin-wrap[aria-pressed="true"] {
	z-index: 100000 !important;
}

.pmd-pin-wrap[aria-pressed="true"] .pmd-pin-icon::before {
	opacity: 1;
	transform: scale(1);
}

/*
 * The pin is a real interactive control (front.js gives its wrapping element
 * role="button" and tabindex="0"), so it gets a focus-visible treatment of
 * its own rather than relying on :hover, which a keyboard user never
 * triggers.
 */
.pmd-pin-wrap:focus-visible {
	outline: 2px solid var(--pmd-color-primary);
	outline-offset: 2px;
	border-radius: var(--pmd-radius-sm);
}

.pmd-pin-wrap:focus-visible .pmd-pin-icon {
	transform: scale(1.1);
}

/*
 * The category glyph inside the pin's head — assets/js/front/front.js's
 * pawPinIcon()/buildPinGlyph(). `.pmd-pin-icon` is the wrapper that groups
 * the pin SVG and its optional glyph as one divIcon `html` element (Leaflet
 * appends it as a single node — see pawPinIcon()'s own docblock), positioned
 * so the glyph can sit centred in the pin's rounded head regardless of the
 * SVG's own hover/active transform.
 */
.pmd-pin-icon {
	display: block;
	position: relative;
	isolation: isolate;
	transform-origin: 50% 100%;
	transition: transform var(--pmd-duration-fast) var(--pmd-ease-out);
}

/* The selected pin's ring: a soft halo round the head, behind the pin. */
.pmd-pin-icon::before {
	position: absolute;
	top: 17px;
	left: 50%;
	z-index: -1;
	width: 42px;
	height: 42px;
	margin: -21px 0 0 -21px;
	background: rgba(15, 23, 42, 0.12);
	background: color-mix(in srgb, var(--pmd-color-accent, var(--pmd-color-primary)) 18%, transparent);
	border-radius: 50%;
	box-shadow: 0 0 0 5px rgba(15, 23, 42, 0.06);
	box-shadow: 0 0 0 5px color-mix(in srgb, var(--pmd-color-accent, var(--pmd-color-primary)) 10%, transparent);
	content: "";
	opacity: 0;
	pointer-events: none;
	transform: scale(0.6);
	transition:
		opacity var(--pmd-duration-normal) var(--pmd-ease-out),
		transform var(--pmd-duration-normal) var(--pmd-ease-out);
}

.pmd-pin-glyph {
	position: absolute;
	top: 38%;
	left: 50%;
	width: 16px;
	height: 16px;
	transform: translate(-50%, -50%);
	pointer-events: none;
}

/*
 * Presets are recoloured white via a CSS mask — never an inlined copy of
 * the preset file's own markup, which is never fetched by this stylesheet
 * or by front.js either; only referenced by URL. front.js sets the
 * mask-image URL itself (element.style.maskImage), per-marker; this class
 * only carries the properties that are the same for every preset glyph.
 */
.pmd-pin-glyph--preset {
	background-color: #ffffff;
	mask-repeat: no-repeat;
	mask-position: center;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	-webkit-mask-position: center;
	-webkit-mask-size: contain;
}

/*
 * Uploads keep their own colours, so a plain white circular badge behind
 * the artwork is what keeps a dark icon legible on a dark pin — the same
 * contrast problem a mask solves for a preset by recolouring it instead.
 */
.pmd-pin-glyph--upload {
	top: 36%;
	width: 20px;
	height: 20px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background-color: #ffffff;
	box-shadow: 0 1px 2px rgba(15, 23, 42, 0.35);
}

.pmd-pin-glyph-img {
	display: block;
	width: 13px;
	height: 13px;
	object-fit: contain;
}

/*
 * The cluster badge (assets/js/front/front.js's clusterIcon()/
 * buildLeafletClusterProvider()): a filled circle sized by member count
 * (34/42/52px, set inline per badge — see clusterIcon()'s docblock for why
 * the size and fill are literal rather than a class per bucket) with the
 * count as its label. Same interactive-control treatment as .pmd-pin-wrap:
 * both wrap a divIcon Leaflet built from a plain HTML string, so neither
 * gets role/tabindex "for free" from Leaflet.
 */
.pmd-cluster-wrap {
	background: none;
	border: 0;
}

.pmd-cluster {
	box-sizing: border-box;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	border: 2px solid #ffffff;
	border-radius: 50%;
	color: #ffffff;
	font-family: inherit;
	font-size: 13px;
	font-weight: var(--pmd-weight-semibold);
	line-height: 1;
	cursor: pointer;
	transition: transform var(--pmd-duration-fast) var(--pmd-ease-out);
	filter: drop-shadow(0 3px 5px rgba(15, 23, 42, 0.35));
}

.pmd-cluster:hover {
	transform: scale(1.08);
}

.pmd-cluster-wrap:focus-visible {
	outline: 2px solid var(--pmd-color-primary);
	outline-offset: 2px;
	border-radius: 50%;
}

.pmd-cluster-wrap:focus-visible .pmd-cluster {
	transform: scale(1.08);
}

@media (prefers-reduced-motion: reduce) {

	.pmd-pin-icon,
	.pmd-pin-icon::before,
	.pmd-cluster {
		transition: none;
	}
}

/* ── The map's place card ────────────────────────────────────── */

/*
 * front.js's buildRichPopupBody() inside Leaflet's popup frame. The frame
 * carries `.pmd-popup` (front.js's PLACE_POPUP_OPTIONS), so these rules
 * reach it in the directory, the explorer and anywhere else the card opens.
 *
 * leaflet.css styles that frame and its content on its own terms — the
 * close button a 24px Tahoma glyph, every link #0078A8 (`.leaflet-container
 * a`), every paragraph a 1.3em margin (`.leaflet-popup-content p`) — so each
 * rule below carries two classes to outrank it, and the frame's own parts
 * read the card surface token: wrapper and tip alike, so the arrow under the
 * card is the card.
 *
 * Two layouts: a place with a photo opens on a 16:9 photo header; one
 * without (`.has-tile`) shows the card list's category tile, 48px, beside
 * its title instead of spending a banner on a lone icon.
 *
 * Radii are concentric: everything inset by the body's 12px padding takes
 * the frame's radius minus that padding.
 */
.pmd-popup .leaflet-popup-content-wrapper {
	padding: 0;
	overflow: hidden;
	color: var(--pmd-color-text);
	text-align: left;
	background: var(--pmd-color-surface-raised);
	border-radius: var(--pmd-radius-xl);
	box-shadow: var(--pmd-shadow-lg);
}

/* Narrower than the viewport on the smallest phones. */
.pmd-popup .leaflet-popup-content {
	width: 288px !important;
	max-width: calc(100vw - 48px);
	margin: 0;
	font-size: var(--pmd-text-sm);
	line-height: var(--pmd-leading-snug);
}

.pmd-popup .leaflet-popup-tip {
	background: var(--pmd-color-surface-raised);
	box-shadow: var(--pmd-shadow-md);
}

/*
 * A 32px round button — over a photo too, hence its own surface and a
 * shadow — whose ::before stretches the hit area to 44px. Three classes:
 * leaflet.css's own rule is `.leaflet-container a.leaflet-popup-close-button`.
 */
.leaflet-popup.pmd-popup a.leaflet-popup-close-button {
	top: 8px;
	right: 8px;
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	padding: 0;
	color: var(--pmd-color-text-muted);
	font-family: var(--pmd-font-sans, inherit);
	font-size: 22px;
	font-weight: var(--pmd-weight-regular);
	line-height: 1;
	background: var(--pmd-color-surface-raised);
	border-radius: var(--pmd-radius-pill);
	box-shadow: var(--pmd-shadow-md);
	transition:
		background-color var(--pmd-duration-fast) var(--pmd-ease-out),
		color var(--pmd-duration-fast) var(--pmd-ease-out);
}

.leaflet-popup.pmd-popup a.leaflet-popup-close-button::before {
	position: absolute;
	inset: -6px;
	content: "";
}

.leaflet-popup.pmd-popup a.leaflet-popup-close-button:hover,
.leaflet-popup.pmd-popup a.leaflet-popup-close-button:focus {
	color: var(--pmd-color-text);
	background: var(--pmd-color-surface-alt);
}

.leaflet-popup.pmd-popup a.leaflet-popup-close-button:focus-visible {
	outline: 2px solid var(--pmd-color-accent, var(--pmd-color-primary));
	outline-offset: 2px;
}

.pmd-pop {
	--pmd-pop-pad: var(--pmd-space-3);
	--pmd-pop-inner-radius: calc(var(--pmd-radius-xl) - var(--pmd-space-3));
	color: var(--pmd-color-text);
	font-family: var(--pmd-font-sans, inherit);
	font-size: var(--pmd-text-sm);
	line-height: var(--pmd-leading-snug);
}

/* The tint a photo loads over, in the frame the photo will fill. */
.pmd-pop .pmd-pop-media {
	position: relative;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	background-color: var(--pmd-color-primary-soft);
}

.pmd-pop .pmd-pop-img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.pmd-pop .pmd-pop-body {
	display: flex;
	flex-direction: column;
	gap: var(--pmd-space-3);
	padding: var(--pmd-pop-pad);
}

.pmd-pop .pmd-pop-head {
	display: flex;
	align-items: flex-start;
	gap: var(--pmd-space-3);
	min-width: 0;
}

/* The close button sits over the compact head: keep the title clear of it. */
.pmd-pop.has-tile .pmd-pop-head {
	padding-right: 32px;
}

.pmd-pop .pmd-pop-tile {
	flex: none;
	width: 48px;
	height: 48px;
	background-color: var(--pmd-color-primary-soft);
	border-radius: var(--pmd-pop-inner-radius);
}

.pmd-pop .pmd-pop-tile .pmd-card-tile-ico {
	width: 50%;
	height: 50%;
}

.pmd-pop .pmd-pop-heading {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}

.pmd-pop .pmd-pop-title {
	margin: 0;
	color: var(--pmd-color-text);
	font-family: var(--pmd-font-display, var(--pmd-font-sans, inherit));
	font-size: var(--pmd-text-md);
	font-weight: var(--pmd-weight-semibold);
	line-height: var(--pmd-leading-tight);
	overflow-wrap: anywhere;
	text-wrap: pretty;
}

.pmd-pop .pmd-pop-cats {
	display: -webkit-box;
	margin: 0;
	overflow: hidden;
	color: var(--pmd-color-text-muted);
	font-size: 13px;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
}

/* The zone, with the card list's pin icon (`.pmd-card-where`). */
.pmd-pop .pmd-pop-addr {
	display: flex;
	align-items: center;
	gap: 4px;
	min-width: 0;
	margin: 0;
	color: var(--pmd-color-text-muted);
	font-size: var(--pmd-text-xs);
}

.pmd-pop .pmd-pop-addr .pmd-ico {
	display: block;
	flex: none;
}

.pmd-pop .pmd-pop-addr span {
	min-width: 0;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

/* Rating and open/closed badge: the card list's `.pmd-card-rating` and `.pmd-tag`. */
.pmd-pop .pmd-pop-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--pmd-space-2);
}

.pmd-pop .pmd-pop-rating {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	color: var(--pmd-color-text);
	font-size: 13px;
	font-weight: var(--pmd-weight-medium);
	font-variant-numeric: tabular-nums;
}

.pmd-pop .pmd-pop-rating .pmd-ico {
	display: block;
	flex: none;
	color: var(--pmd-color-warning);
}

.pmd-pop .pmd-pop-rating .cnt {
	color: var(--pmd-color-text-muted);
	font-weight: var(--pmd-weight-regular);
}

.pmd-pop .pmd-pop-status {
	display: inline-flex;
}

/*
 * The actions, as a button pair: "directions" in outline, "view place"
 * filled with the primary — the token pair Front\DesignSystem keeps at AA
 * (white on #c2410c under the warm preset; the on-primary it computes for
 * any brand colour otherwise). One action alone spans the row.
 */
.pmd-pop .pmd-pop-actions {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--pmd-space-2);
}

.pmd-pop .pmd-pop-action {
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	min-width: 0;
	min-height: 44px;
	padding: 6px var(--pmd-space-2);
	font-family: var(--pmd-font-display, var(--pmd-font-sans, inherit));
	font-size: var(--pmd-text-sm);
	font-weight: var(--pmd-weight-semibold);
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	text-wrap: balance;
	border: 1px solid transparent;
	border-radius: var(--pmd-pop-inner-radius);
	transition:
		background-color var(--pmd-duration-fast) var(--pmd-ease-out),
		border-color var(--pmd-duration-fast) var(--pmd-ease-out),
		color var(--pmd-duration-fast) var(--pmd-ease-out),
		transform var(--pmd-duration-fast) var(--pmd-ease-out);
}

.pmd-pop .pmd-pop-action:only-child {
	grid-column: 1 / -1;
}

.pmd-pop .pmd-pop-action:active {
	transform: scale(0.96);
}

.pmd-pop .pmd-pop-action-secondary,
.pmd-pop .pmd-pop-action-secondary:hover,
.pmd-pop .pmd-pop-action-secondary:focus {
	color: var(--pmd-color-text);
}

.pmd-pop .pmd-pop-action-secondary {
	background: var(--pmd-color-surface-raised);
	border-color: var(--pmd-color-border-strong);
}

.pmd-pop .pmd-pop-action-secondary:hover {
	background: var(--pmd-color-primary-soft);
	border-color: var(--pmd-color-accent, var(--pmd-color-primary));
}

.pmd-pop .pmd-pop-action-secondary .pmd-ico {
	display: block;
	flex: none;
	color: var(--pmd-color-accent, var(--pmd-color-primary));
}

.pmd-pop .pmd-pop-action-primary,
.pmd-pop .pmd-pop-action-primary:hover,
.pmd-pop .pmd-pop-action-primary:focus {
	color: var(--pmd-color-on-primary);
}

.pmd-pop .pmd-pop-action-primary {
	background: var(--pmd-color-primary);
	box-shadow: var(--pmd-shadow-sm);
}

.pmd-pop .pmd-pop-action-primary:hover {
	background: var(--pmd-color-primary-hover);
}

.pmd-pop .pmd-pop-action:focus-visible {
	outline: 2px solid var(--pmd-color-accent, var(--pmd-color-primary));
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {

	.leaflet-popup.pmd-popup a.leaflet-popup-close-button,
	.pmd-pop .pmd-pop-action {
		transition: none;
	}

	.pmd-pop .pmd-pop-action:active {
		transform: none;
	}
}

/* ── The design's three-column split ─────────────────────────── */

@media (min-width: 1024px) {

	.pmd-directory {
		height: 80vh;
		min-height: 640px;
		max-height: 900px;
	}

	.pmd-dir-split {
		grid-template-columns: 220px minmax(340px, 400px) minmax(0, 1fr);
	}

	.pmd-dir-filters {
		padding: var(--pmd-space-5) var(--pmd-space-4);
		overflow-y: auto;
		border-right: 1px solid var(--pmd-color-border);
		border-bottom: 0;
	}

	.pmd-dir-cards {
		padding: var(--pmd-space-4);
		overflow-y: auto;
		border-right: 1px solid var(--pmd-color-border);
	}

	.pmd-dir-map {
		min-height: 0;
	}

	/* Both result columns are on screen here, whatever `pmd_view` says. */
	.pmd-view-map .pmd-dir-cards {
		display: flex;
	}

	.pmd-view-list .pmd-dir-map,
	.pmd-view-map .pmd-dir-map {
		display: block;
		min-height: 0;
	}

	/*
	 * Neither of the two narrow-layout ways between the columns has anything
	 * to offer here: both columns are already visible.
	 */
	.pmd-viewseg,
	.pmd-fab {
		display: none;
	}

	/*
	 * The filter column is always open above the split, so the disclosure has
	 * to stop disclosing. `content-visibility` on ::details-content is the
	 * standard way to say that — the same property the UA sheet uses to hide a
	 * closed <details>.
	 *
	 * The summary is hidden only where that selector is understood. A browser
	 * without it drops the @supports block, keeps the summary on screen, and
	 * leaves a visitor with a filter column they open in one click; hiding the
	 * summary unconditionally would leave them with filters they cannot reach
	 * at all.
	 */
	.pmd-fdisclosure {
		display: flex;
		flex: 1;
		flex-direction: column;
	}

	.pmd-fdisclosure::details-content {
		display: flex;
		flex: 1;
		flex-direction: column;
		block-size: auto;
		content-visibility: visible;
	}

	@supports selector(::details-content) {

		.pmd-fsummary {
			display: none;
		}
	}

	.pmd-fbody {
		flex: 1;
		padding-top: 0;
	}

	/* The design's own measurements, back where the pointer is a mouse. */
	.pmd-fselect {
		height: 36px;
	}

	.pmd-chips {
		flex-wrap: wrap;
		padding-block: 0;
		overflow: visible;
	}

	.pmd-chip {
		height: 30px;
		padding: 0 12px;
	}

	.pmd-sort-btn {
		min-height: 34px;
	}

	.pmd-apply {
		min-height: 34px;
		padding: 0 14px;
	}

	.pmd-clear {
		min-height: 0;
		padding: 0;
	}
}
