/**
 * IPMX Registry public directory.
 *
 * Buildless, hand-authored. Scoped under .ipmx-directory so it cannot bleed into
 * the host theme. Modern card grid + list views, tier badges, and pagination.
 */

/* OCR-B "scan-reader" face for the IPMX Certified lockup — the same font the
   certified-badge renderer bakes into the issued artifacts (see fonts/README.md). */
@font-face {
	font-family: "IPMX OCR-B";
	src: url("fonts/ocrb10.otf") format("opentype");
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}

.ipmx-directory {
	/* IPMX brand palette (Brand Guidelines, Dec 2023): teal #007D8F + black + white.
	   --ipmx-accent is the brand-compliant teal (AA-safe on white, ~4.85:1) used for
	   links/text/primary; --ipmx-accent-bright is the brighter cyan-teal ipmx.io uses
	   live (decorative fills/hovers only — too light for text). Typography matches
	   ipmx.io: Montserrat headings + Lato body. Everything is a custom property so a
	   host-aware shell can re-skin per brand (AIMS) — see bead bfu. */
	--ipmx-teal: #007d8f;
	--ipmx-teal-bright: #00b7c4;
	--ipmx-accent: var(--ipmx-teal);
	--ipmx-accent-bright: var(--ipmx-teal-bright);
	--ipmx-ink: #111418;
	--ipmx-muted: #667085;
	--ipmx-line: #e4e7ec;
	--ipmx-bg-soft: #f7f8fa;
	--ipmx-surface: #fff;
	/* Listing cards sit a shade off pure white (~9%) so they read as soft panels
	   against the page rather than blending into it. */
	--ipmx-card: #e9ebef;
	/* Neutral medium-dark field behind product photos, so vendor shots — light,
	   dark, or transparent (alpha) — sit on one predictable, gracefully-contrasting
	   backing. Subtle gradient for a little depth. The registry is light-only
	   (owner decision 2026-08-29: the host sites do not support dark mode). */
	--ipmx-image-field: linear-gradient(135deg, #69707f, #414651);
	--ipmx-radius: 12px;
	--ipmx-font-head: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	--ipmx-font-body: "Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	color: var(--ipmx-ink);
	font-family: var(--ipmx-font-body);
	font-size: 16px;
	line-height: 1.45;
}

/* Host-aware re-skin seam (bead bfu): the AIMS host (solutions.aimsalliance.org)
   swaps the accent token. AIMS shares IPMX's teal family — these values are
   sampled from the live AIMS site (#007788 primary, AA-safe on white; #048697 the
   brighter teal it uses for emphasis). Header-only re-skin: the layout is
   identical to the IPMX view; only the logo, accent, and subtitle change. */
.ipmx-directory[data-ipmx-brand="aims"] {
	--ipmx-accent: #007788;
	--ipmx-accent-bright: #048697;
}

/* Headings use the Montserrat brand face; body inherits Lato from the root. */
.ipmx-directory h1,
.ipmx-directory h2,
.ipmx-directory h3,
.ipmx-directory__title,
.ipmx-card__name,
.ipmx-detail__name {
	font-family: var(--ipmx-font-head);
}

.ipmx-directory__inner {
	max-width: 1200px;
	margin: 0 auto;
	padding: 2rem 1.25rem 4rem;
}

/* Brand band (Shell\Brand): the registry's own IPMX header/footer that sit inside
   the host theme chrome. The data-ipmx-brand attribute is the per-host swap seam
   (bead bfu). */
.ipmx-brand {
	display: flex;
	align-items: center;
	gap: 0.9rem;
	margin: 0 0 1.75rem;
	padding-bottom: 1.1rem;
	border-bottom: 2px solid var(--ipmx-accent);
}

.ipmx-brand__logo-link {
	display: inline-flex;
	line-height: 0;
}

.ipmx-brand__logo {
	display: block;
	height: 44px;
	width: auto;
}

.ipmx-brand__divider {
	width: 1px;
	height: 26px;
	background: var(--ipmx-line);
}

.ipmx-brand__subtitle {
	font-family: var(--ipmx-font-head);
	font-weight: 600;
	font-size: 1.05rem;
	letter-spacing: 0.01em;
	color: var(--ipmx-ink);
}

/* Co-branded Vendor Portal lockup (bead 46y): AIMS mark (slightly taller) · a thin
   accent rule · the IPMX mark · the surface label, all vertically centered (the
   .ipmx-brand flex already centers them). */
.ipmx-brand--cobrand picture {
	display: inline-flex;
	line-height: 0;
}

.ipmx-brand__logo--aims {
	height: 48px;
}

.ipmx-brand__logo--ipmx {
	height: 44px;
}

.ipmx-brand__rule {
	width: 1px;
	height: 30px;
	flex: 0 0 auto;
	border-radius: 1px;
	/* A thin VERTICAL divider standing between the AIMS and IPMX marks, with a
	   simple metallic sheen: the accent fades in from both ends and brightens
	   through the middle (a highlight running down its length). */
	background: linear-gradient(
		to bottom,
		transparent,
		var(--ipmx-accent) 25%,
		var(--ipmx-accent-bright) 50%,
		var(--ipmx-accent) 75%,
		transparent
	);
}

.ipmx-brand__subtitle--lg {
	font-size: 1.2rem;
}

.ipmx-brand-footer {
	margin-top: 3rem;
	padding-top: 1.25rem;
	border-top: 1px solid var(--ipmx-line);
	color: var(--ipmx-muted);
	font-size: 0.85rem;
}

.ipmx-brand-footer__link {
	color: var(--ipmx-accent);
	text-decoration: none;
}

.ipmx-brand-footer__link:hover {
	text-decoration: underline;
}

.ipmx-directory__head {
	margin-bottom: 1.5rem;
}

.ipmx-directory__title {
	margin: 0 0 0.75rem;
	font-size: 1.9rem;
	font-weight: 700;
	letter-spacing: -0.01em;
}

/* AIMS host (bead bfu): the brand band already names the registry "Vendor
   Solutions", so the IPMX-worded list title is hidden visually but kept in the
   DOM for a single semantic h1 / SEO. Standard visually-hidden pattern. */
.ipmx-directory__title--sr {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
}

.ipmx-directory__bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	flex-wrap: wrap;
	padding-bottom: 0.75rem;
	border-bottom: 1px solid var(--ipmx-line);
}

.ipmx-directory__count {
	color: var(--ipmx-muted);
	font-size: 0.95rem;
}

.ipmx-directory__views {
	display: inline-flex;
	border: 1px solid var(--ipmx-line);
	border-radius: 999px;
	overflow: hidden;
}

.ipmx-directory__view {
	padding: 0.35rem 0.9rem;
	font-size: 0.85rem;
	text-decoration: none;
	color: var(--ipmx-muted);
	background: var(--ipmx-surface);
}

.ipmx-directory__view.is-active {
	background: var(--ipmx-ink);
	color: #fff;
}

/* Filters: search-first row + collapsible facet panel */
.ipmx-filters {
	margin: 1.25rem 0 1.5rem;
}

.ipmx-filters__search {
	display: flex;
	gap: 0.5rem;
	align-items: stretch;
	flex-wrap: wrap;
}

.ipmx-filters__search input[type="search"] {
	flex: 1 1 320px;
	min-width: 0;
	padding: 0.6rem 0.8rem;
	border: 1px solid var(--ipmx-line);
	border-radius: 10px;
	font-size: 1rem;
	background: var(--ipmx-surface);
}

.ipmx-filters__search-go {
	padding: 0.6rem 1.1rem;
	border: 0;
	border-radius: 10px;
	background: var(--ipmx-accent);
	color: #fff;
	font-weight: 600;
	cursor: pointer;
	transition: background 0.15s ease;
}

.ipmx-filters__search-go:hover {
	background: var(--ipmx-accent-bright);
}

.ipmx-filters__toggle,
.ipmx-filters__sort {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	padding: 0.6rem 0.95rem;
	border: 1px solid var(--ipmx-line);
	border-radius: 10px;
	background: var(--ipmx-surface);
	color: var(--ipmx-ink);
	font-weight: 600;
	cursor: pointer;
}

.ipmx-filters__toggle .dashicons {
	font-size: 1.1em;
	width: auto;
	height: auto;
}

.ipmx-filters__badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 1.3em;
	height: 1.3em;
	padding: 0 0.35em;
	border-radius: 999px;
	background: var(--ipmx-accent);
	color: #fff;
	font-size: 0.72rem;
}

.ipmx-filters__panel {
	display: flex;
	flex-wrap: wrap;
	gap: 1.25rem 2rem;
	margin-top: 1rem;
	padding: 1.1rem 1.25rem;
	border: 1px solid var(--ipmx-line);
	border-radius: var(--ipmx-radius);
	background: var(--ipmx-bg-soft);
}

/* JS collapses the panel by default; it opens when the form is expanded. */
.ipmx-has-js .ipmx-filters:not(.is-expanded) .ipmx-filters__panel {
	display: none;
}

.ipmx-filters__group {
	display: flex;
	flex-direction: column;
	gap: 0.45rem;
	border: 0;
	margin: 0;
	padding: 0;
	min-width: 180px;
}

.ipmx-filters__label {
	font-size: 0.78rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--ipmx-muted);
	padding: 0;
}

.ipmx-facet {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	font-size: 0.9rem;
	cursor: pointer;
}

.ipmx-facet__label {
	flex: 1 1 auto;
}

.ipmx-facet__count {
	color: var(--ipmx-muted);
	font-size: 0.78rem;
	font-variant-numeric: tabular-nums;
}

/* The checkbox rows sit in their own column so a long group can scroll
   independently of the legend + filter input above it. */
.ipmx-filters__options {
	display: flex;
	flex-direction: column;
	gap: 0.45rem;
}

/* Long facet groups (e.g. Category) become a searchable, scrollable list so they
   don't run the panel down the page. The list caps its height and scrolls; the
   filter input above narrows it by typing (JS), and is hidden by the JS-filter. */
.ipmx-filters__group--long .ipmx-filters__options {
	max-height: 16rem;
	overflow-y: auto;
	padding: 0.5rem 0.6rem;
	border: 1px solid var(--ipmx-line);
	border-radius: 8px;
	background: var(--ipmx-surface);
	scrollbar-width: thin;
	/* Scroll-shadow affordance: soft cover fades (local, move with content) reveal
	   a faint edge shadow (scroll, pinned) only when there's more to scroll to — a
	   clear "this list scrolls" cue even where the OS auto-hides the scrollbar. */
	background-image:
		linear-gradient(var(--ipmx-surface) 30%, transparent),
		linear-gradient(transparent, var(--ipmx-surface) 70%),
		radial-gradient(farthest-side at 50% 0, rgba(17, 20, 24, 0.12), transparent),
		radial-gradient(farthest-side at 50% 100%, rgba(17, 20, 24, 0.12), transparent);
	background-position: top, bottom, top, bottom;
	background-repeat: no-repeat;
	background-size: 100% 2rem, 100% 2rem, 100% 0.7rem, 100% 0.7rem;
	background-attachment: local, local, scroll, scroll;
}

.ipmx-facet-filter {
	width: 100%;
	box-sizing: border-box;
	padding: 0.3rem 0.5rem;
	font-size: 0.85rem;
	color: var(--ipmx-ink);
	background: var(--ipmx-surface);
	border: 1px solid var(--ipmx-line);
	border-radius: 8px;
}

.ipmx-facet-filter:focus {
	outline: none;
	border-color: var(--ipmx-accent);
}

/* A facet row hidden by the type-to-filter search (display:flex would otherwise
   win over the bare [hidden] attribute). */
.ipmx-facet[hidden] {
	display: none;
}

/* Shown by JS when a filter term matches nothing. */
.ipmx-facet-empty {
	font-size: 0.85rem;
	color: var(--ipmx-muted);
	padding: 0.15rem 0;
}

/* Domain headings within a scrollable checkbox list (the secondary-categories
   picker). Sticky so the current domain stays in view while scrolling. */
.ipmx-facet-group + .ipmx-facet-group {
	margin-top: 0.35rem;
}

.ipmx-facet-group__head {
	position: sticky;
	top: -0.5rem;
	margin: 0 -0.6rem 0.25rem;
	padding: 0.2rem 0.6rem;
	background: var(--ipmx-surface);
	font-size: 0.72rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--ipmx-muted);
}

.ipmx-filters__actions {
	flex-basis: 100%;
	display: flex;
	align-items: center;
	gap: 1rem;
}

.ipmx-filters__apply {
	padding: 0.55rem 0.9rem;
	border: 0;
	border-radius: 8px;
	background: var(--ipmx-accent);
	color: #fff;
	font-weight: 600;
	cursor: pointer;
	transition: background 0.15s ease;
}

.ipmx-filters__apply:hover {
	background: var(--ipmx-accent-bright);
}

.ipmx-filters__clear {
	color: var(--ipmx-muted);
	text-decoration: none;
	font-size: 0.9rem;
}

/* With JS, the panel auto-submits on change, so the Apply button is optional. */
.ipmx-has-js .ipmx-filters__apply {
	display: none;
}

/* Results: grid (default) */
.ipmx-directory__results {
	list-style: none;
	margin: 1.5rem 0 0;
	padding: 0;
	display: grid;
	gap: 1.1rem;
	grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}

/* Results: list */
.ipmx-directory__results--list {
	grid-template-columns: 1fr;
	gap: 0.6rem;
}

.ipmx-card {
	border: 1px solid var(--ipmx-line);
	border-radius: var(--ipmx-radius);
	background: var(--ipmx-card);
	transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.ipmx-card:hover {
	box-shadow: 0 6px 24px rgba(16, 24, 40, 0.1);
	transform: translateY(-2px);
}

.ipmx-card__link {
	display: flex;
	flex-direction: column;
	height: 100%;
	text-decoration: none;
	color: inherit;
}

.ipmx-card__thumb {
	display: block;
	box-sizing: border-box;
	aspect-ratio: 16 / 10;
	overflow: hidden;
	border-radius: var(--ipmx-radius) var(--ipmx-radius) 0 0;
	background: var(--ipmx-image-field);
	/* A small even inset frames the photo against the neutral field, so the image
	   reads as a deliberately-framed element even when it bleeds to the edge. */
	padding: 6px;
}

/* Product photo: fit the whole image on the neutral image field so varying
   vendor aspect ratios stay graceful (no cropping) and transparent shots sit on
   the same predictable backing in either theme. The subtle rounding + soft
   shadow lift the photo a touch off the field for a modern, framed look. */
.ipmx-card__img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	background: var(--ipmx-image-field);
	display: block;
	border-radius: 6px;
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
}

/* Per-product / per-vendor image background (the vendor's choice). White (the
   product default) and black are solid with a subtle inset edge so they still
   read against the card and carry a little polish; grey keeps the neutral
   gradient. Re-pointing --ipmx-image-field on the thumb cascades to the
   contained image too. */
.ipmx-card__thumb[data-ipmx-img-bg="white"],
.ipmx-card__vendor-logo[data-ipmx-img-bg="white"] {
	--ipmx-image-field: #ffffff;
	box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.07);
}

.ipmx-card__thumb[data-ipmx-img-bg="black"],
.ipmx-card__vendor-logo[data-ipmx-img-bg="black"] {
	--ipmx-image-field: #0c0d0f;
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

/* None: no field and no edge — the picture sits directly on the card surface.
   This is the company-logo default (a frame behind a wide, transparent wordmark
   reads heavy); it is also offered for product images. */
.ipmx-card__thumb[data-ipmx-img-bg="none"] {
	--ipmx-image-field: transparent;
	box-shadow: none;
	padding: 0;
}

.ipmx-card__thumb[data-ipmx-img-bg="none"] .ipmx-card__img {
	box-shadow: none;
	border-radius: 0;
}

.ipmx-card__body {
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
	padding: 0.85rem 0.95rem 1rem;
	/* Grow to fill the card's height (grid cells stretch to the tallest in a row),
	   so the recognition badge in .ipmx-card__meta can anchor to the bottom rather
	   than floating directly under the category text. */
	flex: 1 1 auto;
}

.ipmx-card__name {
	font-weight: 600;
	font-size: 1.02rem;
	line-height: 1.25;
}

.ipmx-card__vendor {
	color: var(--ipmx-muted);
	font-size: 0.88rem;
}

/* Company-logo chip. The default ('none') is frameless — the mark sits directly
   on the card surface. When a vendor frames their logo (grey / white / black),
   the chip shows the chosen field with a little padding + rounding so the logo
   reads as a deliberately-framed element. */
.ipmx-card__vendor-logo {
	display: inline-flex;
	align-items: center;
	align-self: flex-start;
	border-radius: 5px;
}

.ipmx-card__vendor-logo[data-ipmx-img-bg="grey"],
.ipmx-card__vendor-logo[data-ipmx-img-bg="white"],
.ipmx-card__vendor-logo[data-ipmx-img-bg="black"] {
	background: var(--ipmx-image-field);
	padding: 3px 6px;
}

.ipmx-card__vendor-logo img {
	max-height: 24px;
	max-width: 100%;
	width: auto;
	height: auto;
	object-fit: contain;
}

.ipmx-card__category {
	margin-top: 0.2rem;
	font-size: 0.82rem;
	color: var(--ipmx-accent, #2d6cdf);
}

.ipmx-card__meta {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	/* Push the recognition badge (IPMX Certified today; JT-NM and others later) to
	   the bottom of the card body, so badges line up along the bottom edge across a
	   grid row regardless of how much name/category text sits above. The body's
	   1rem bottom padding supplies the margin beneath. List view resets this. */
	margin-top: auto;
	flex-wrap: wrap;
}

.ipmx-card__icid {
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: 0.78rem;
	color: var(--ipmx-muted);
}

/* Integrated IPMX Certified lockup (Shell\Brand::certified_lockup): the IPMX mark
   + "Certified" in OCR-B on a charcoal chip, echoing the issued certification
   badge. Replaces the old logo-mark + "IPMX Certified" pill (which read as
   "IPMX IPMX Certified"). */
.ipmx-cert-lockup {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	flex: 0 0 auto;
	padding: 0.28rem 0.5rem;
	border-radius: 6px;
	background: #2b2b2b;
	line-height: 1;
}

.ipmx-cert-lockup__logo {
	display: block;
	height: 13px;
	width: auto;
}

.ipmx-cert-lockup__word {
	font-family: "IPMX OCR-B", ui-monospace, "Lucida Console", monospace;
	font-size: 0.6rem;
	letter-spacing: 0.2em;
	padding-left: 0.2em;
	text-transform: uppercase;
	color: #d4d7db;
}

/* Certified cards carry a faint teal border to lift them in the grid (IPMX-first). */
.ipmx-card--tier-ipmx-certified {
	border-color: rgba(0, 125, 143, 0.35);
}

/* Detail-page certified badge block (Shell\Brand::certified_badge): a charcoal
   lockup echoing the issued badge — CERTIFIED in OCR-B over the IPMX mark + ICID.
   Shown until issuance supplies the real per-product badge artifact (ojq.2). */
.ipmx-cert-badge {
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	gap: 0.6rem;
	margin: 0;
	padding: 1rem 1.4rem;
	border: 2px solid #000;
	border-radius: 12px;
	background: #2b2b2b;
	max-width: 260px;
}

.ipmx-cert-badge__top {
	font-family: "IPMX OCR-B", ui-monospace, "Lucida Console", monospace;
	font-size: 0.85rem;
	letter-spacing: 0.35em;
	padding-left: 0.35em;
	text-transform: uppercase;
	color: #d4d7db;
}

.ipmx-cert-badge__logo {
	display: block;
	width: 180px;
	max-width: 100%;
	height: auto;
}

.ipmx-cert-badge__icid {
	font-family: "IPMX OCR-B", ui-monospace, "Lucida Console", monospace;
	font-size: 0.72rem;
	letter-spacing: 0.08em;
	color: #b3b9c2;
}

/* List view: horizontal card layout */
.ipmx-directory__results--list .ipmx-card__link {
	flex-direction: row;
	/* Stretch so the preview box fills the card's full height (down to the badge
	   row), with its top/bottom margins giving even inset above and below. */
	align-items: stretch;
	gap: 1rem;
}

.ipmx-directory__results--list .ipmx-card__thumb {
	width: 120px;
	flex: 0 0 120px;
	/* A detached, evenly-margined rounded box: even breathing room from the card's
	   edges, slightly less rounding than the grid box, and a thin even inset around
	   the picture. Height comes from the stretched row (not a fixed aspect ratio),
	   so the box runs the full content height. */
	border-radius: 8px;
	margin: 10px 0 10px 10px;
	padding: 4px;
}

.ipmx-directory__results--list .ipmx-card__body {
	padding: 0.6rem 1rem 0.6rem 0;
	/* Tighten the leading (~20%) between name, vendor, category, and the badge row
	   so the certified badge doesn't make list cards taller. Grid is unchanged. */
	gap: 0.28rem;
	/* List cards stack content from the top (the pill row sits just under the
	   category, not pinned to the card's full height) — undo the grid's grow. */
	flex: 0 1 auto;
}

/* A second ~20% tightening of just the lines above + below the category (the
   shared 0.28rem body gap stays, so name → manufacturer spacing is unchanged). */
.ipmx-directory__results--list .ipmx-card__category {
	margin-top: 0.07rem;
}

.ipmx-directory__results--list .ipmx-card__meta {
	margin-top: 0.17rem;
}

/* Tier badges */
.ipmx-badge {
	display: inline-block;
	padding: 0.15rem 0.55rem;
	border-radius: 999px;
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.01em;
	background: var(--ipmx-bg-soft);
	color: var(--ipmx-muted);
	border: 1px solid var(--ipmx-line);
}

.ipmx-badge--ipmx-certified {
	background: #e6f4f6;
	color: #00606e;
	border-color: #b8e0e6;
}

.ipmx-badge--ipmx-test-infrastructure {
	background: #eef2ff;
	color: #3538cd;
	border-color: #c7d0fe;
}

/* Pagination */
.ipmx-directory__pagination {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 1.25rem;
	margin-top: 2rem;
}

.ipmx-directory__pagination a {
	text-decoration: none;
	color: var(--ipmx-ink);
	font-weight: 600;
}

.ipmx-directory__page-of {
	color: var(--ipmx-muted);
	font-size: 0.9rem;
}

.ipmx-directory__empty {
	margin-top: 2rem;
	color: var(--ipmx-muted);
}

/* Detail page */
.ipmx-detail__back {
	margin: 0 0 1rem;
}

.ipmx-detail__back a {
	text-decoration: none;
	color: var(--ipmx-muted);
}

.ipmx-detail__grid {
	display: grid;
	grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
	gap: 2rem;
	align-items: start;
}

@media (max-width: 782px) {
	.ipmx-detail__grid {
		grid-template-columns: 1fr;
	}
}

.ipmx-detail__noimage,
.ipmx-gallery__slide img {
	width: 100%;
	border-radius: var(--ipmx-radius);
}

/* Cap the product image so the desktop hero stays short (content rises above the
   fold) and varying vendor aspect ratios are shown whole, not cropped. */
.ipmx-gallery__slide img {
	box-sizing: border-box;
	aspect-ratio: 16 / 10;
	max-height: 340px;
	object-fit: contain;
	background: var(--ipmx-image-field);
	/* Same framed treatment as the card thumbs: an even inset on the neutral
	   field, gentle rounding, and a soft shadow for a touch of dimension. */
	padding: 8px;
	box-shadow: 0 1px 4px rgba(0, 0, 0, 0.22);
}

/* No image: a compact branded placeholder (the square IPMX mark) rather than a
   tall empty box. */
.ipmx-detail__noimage {
	aspect-ratio: 5 / 3;
	max-height: 220px;
	background:
		var(--ipmx-bg-soft) url("img/ipmx-icon-192.png") center / 56px no-repeat;
	opacity: 0.7;
}

.ipmx-gallery {
	position: relative;
}

.ipmx-gallery__track {
	display: flex;
	gap: 0.75rem;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: thin;
}

.ipmx-gallery__slide {
	flex: 0 0 100%;
	margin: 0;
	scroll-snap-align: center;
}

.ipmx-gallery__nav {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	width: 2.2rem;
	height: 2.2rem;
	border-radius: 999px;
	border: 1px solid var(--ipmx-line);
	background: rgba(255, 255, 255, 0.9);
	cursor: pointer;
	font-size: 1rem;
}

.ipmx-gallery__nav--prev {
	left: 0.5rem;
}

.ipmx-gallery__nav--next {
	right: 0.5rem;
}

.ipmx-detail__identity .ipmx-badge,
.ipmx-detail__identity .ipmx-cert-lockup {
	margin-bottom: 0.6rem;
}

.ipmx-detail__name {
	margin: 0.2rem 0 0.4rem;
	font-size: 1.7rem;
	line-height: 1.2;
}

.ipmx-detail__vendor {
	margin: 0 0 1rem;
	color: var(--ipmx-muted);
}

/* Vendor logo. Honors the vendor's chosen frame (None / Grey / White / Black);
   'none' (the logo default) is frameless. White/black/grey share the card chip's
   --ipmx-image-field treatment via the data-ipmx-img-bg variants above. */
.ipmx-detail__vendor-logo {
	margin: 0 0 0.5rem;
	display: inline-flex;
	border-radius: 6px;
}

.ipmx-detail__vendor-logo[data-ipmx-img-bg="grey"],
.ipmx-detail__vendor-logo[data-ipmx-img-bg="white"],
.ipmx-detail__vendor-logo[data-ipmx-img-bg="black"] {
	background: var(--ipmx-image-field);
	padding: 6px 9px;
}

.ipmx-detail__vendor-logo[data-ipmx-img-bg="white"] {
	box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.07);
}

.ipmx-detail__vendor-logo[data-ipmx-img-bg="black"] {
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.ipmx-detail__vendor-logo img {
	max-height: 48px;
	max-width: 220px;
	width: auto;
	height: auto;
	object-fit: contain;
}

.ipmx-detail__roles {
	margin: 0 0 1rem;
	font-size: 0.92rem;
}

.ipmx-detail__roles-label {
	color: var(--ipmx-muted);
	font-weight: 600;
	margin-right: 0.35rem;
}

.ipmx-detail__role {
	display: inline-block;
	padding: 0.1rem 0.55rem;
	margin: 0 0.25rem 0.25rem 0;
	border: 1px solid var(--ipmx-line);
	border-radius: 999px;
	font-size: 0.85rem;
	text-decoration: none;
}

.ipmx-detail__facts {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 0.35rem 1rem;
	margin: 1rem 0;
	font-size: 0.92rem;
}

.ipmx-detail__facts dt {
	color: var(--ipmx-muted);
	font-weight: 600;
}

.ipmx-detail__facts dd {
	margin: 0;
}

.ipmx-detail__badge {
	margin: 1.25rem 0 0;
}

.ipmx-detail__badge-img {
	display: block;
	width: 260px;
	height: auto;
	max-width: 100%;
}

.ipmx-detail__section {
	margin-top: 2.5rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--ipmx-line);
}

.ipmx-detail__section h2 {
	margin: 0 0 1rem;
	font-size: 1.3rem;
}

/* Short brand-teal accent under each section heading. */
.ipmx-detail__section h2::after {
	content: "";
	display: block;
	width: 2.5rem;
	height: 3px;
	margin-top: 0.45rem;
	border-radius: 2px;
	background: var(--ipmx-accent);
}

.ipmx-detail__section h3 {
	font-family: var(--ipmx-font-head);
	font-size: 1rem;
	margin: 1.25rem 0 0.6rem;
}

.ipmx-detail__terms {
	list-style: none;
	margin: 0 0 1rem;
	padding: 0;
}

.ipmx-detail__terms > li {
	margin-bottom: 0.5rem;
}

/* Each certified profile/capability is a card that links to its spec; the whole
   box lifts on hover (like a directory card) and groups the feature with its
   per-feature coverage attestation / qualification (beads krh / ckp / p5r). */
.ipmx-term {
	display: block;
	padding: 0.7rem 0.85rem;
	border: 1px solid var(--ipmx-line);
	border-left: 3px solid var(--ipmx-accent);
	border-radius: 8px;
	background: var(--ipmx-surface);
	color: inherit;
	text-decoration: none;
}

a.ipmx-term {
	transition: box-shadow 0.15s ease, transform 0.15s ease;
}

a.ipmx-term:hover,
a.ipmx-term:focus-visible {
	box-shadow: 0 6px 24px rgba(16, 24, 40, 0.1);
	transform: translateY(-2px);
}

.ipmx-detail__version {
	color: var(--ipmx-muted);
	font-weight: 400;
	font-size: 0.85em;
}

/* Certification documents (PQCR, Test plan) link to their source doc. */
.ipmx-detail__doclink {
	color: var(--ipmx-accent);
	text-decoration: none;
}

.ipmx-detail__doclink:hover {
	text-decoration: underline;
}

.ipmx-detail__doclink-out.dashicons {
	width: auto;
	height: auto;
	font-size: 0.7em;
	line-height: 1;
	vertical-align: super;
	color: #b3b9c2;
}

/* Subtle "pop-out" affordance: hidden until hover, then fades up to light grey
   at about half the label size. */
.ipmx-term__out.dashicons {
	width: auto;
	height: auto;
	font-size: 0.62em;
	line-height: 1;
	vertical-align: super;
	color: #b3b9c2;
	opacity: 0;
	transform: translateY(3px);
	transition: opacity 0.18s ease, transform 0.18s ease;
}

a.ipmx-term:hover .ipmx-term__out,
a.ipmx-term:focus-visible .ipmx-term__out {
	opacity: 1;
	transform: translateY(0);
}

.ipmx-detail__modes {
	list-style: none;
	margin: 0.5rem 0 0;
	padding-left: 1rem;
}

.ipmx-detail__modes > li {
	margin-bottom: 0.4rem;
}

.ipmx-term--mode {
	border-left-width: 2px;
	font-size: 0.92rem;
}

/* IPMX-claim transport-coverage attestation, shown with each certified feature
   (beads ipmx-registry-krh / ckp / p5r). Deliberately neutral — no good/bad
   colour. Both the full-coverage note and the partial-coverage qualification
   render as a block UNDERNEATH the feature, reading the same. */
.ipmx-detail__coverage,
.ipmx-detail__qualification {
	margin: 0.3rem 0 0;
	padding-left: 0.6rem;
	border-left: 3px solid var(--ipmx-line);
	font-size: 0.9rem;
}

.ipmx-detail__coverage {
	color: var(--ipmx-muted);
}

.ipmx-detail__qualification {
	color: #344054;
}

.ipmx-detail__description {
	max-width: 70ch;
	color: #344054;
}

/* =========================================================================
   Member portal (Portal + MemberProducts + MemberVendor). The portal renders
   under .ipmx-portal.ipmx-directory, so it already inherits the brand tokens
   and Montserrat/Lato; this styles its forms, controls and product cards.
   ========================================================================= */

.ipmx-portal__products {
	list-style: none;
	margin: 1.5rem 0 0;
	padding: 0;
	display: grid;
	gap: 1rem;
}

.ipmx-portal__product {
	padding: 1rem 1.1rem;
	border: 1px solid var(--ipmx-line);
	border-radius: var(--ipmx-radius);
	background: var(--ipmx-surface);
}

.ipmx-portal .description {
	color: var(--ipmx-muted);
	font-size: 0.88rem;
}

.ipmx-portal a {
	color: var(--ipmx-accent);
}

/* Form controls */
.ipmx-portal input[type="text"],
.ipmx-portal input[type="url"],
.ipmx-portal input[type="email"],
.ipmx-portal input[type="search"],
.ipmx-portal input[type="password"],
.ipmx-portal input[type="number"],
.ipmx-portal input[type="date"],
.ipmx-portal select,
.ipmx-portal textarea {
	width: 100%;
	max-width: 440px;
	/* Border-box so a width:100% control's padding + border stay INSIDE the form
	   (matching the category filter list, which is border-box too) rather than
	   overflowing to the page edge. */
	box-sizing: border-box;
	padding: 0.55rem 0.7rem;
	border: 1px solid var(--ipmx-line);
	border-radius: 8px;
	background: var(--ipmx-surface);
	color: var(--ipmx-ink);
	font: inherit;
}

/* The Description textarea spans the full form width — auto-expanding like the
   secondary-category filter list it sits beside, with the same left/right inset —
   rather than the narrower cap the short single-line inputs use. */
.ipmx-portal textarea {
	display: block;
	width: 100%;
	max-width: none;
	min-height: 6rem;
	margin-top: 0.35rem;
}

/* Test-admin event detail forms (event editor, test scope, event documents): every
   control shares the single-line input's width cap so the fields line up on both
   edges — the description / instructions textareas included, rather than running
   full-width past the shorter inputs. */
.ipmx-portal__form--event textarea,
.ipmx-portal__form--scope textarea,
.ipmx-portal__event-docs textarea {
	max-width: 440px;
}

/* Stack each field UNDER its label (like the description textarea already does) so
   the single-line inputs start at the same left edge and end at the same 440px
   right edge — true alignment the inline "label input" pairing didn't give. The
   item-checkbox labels keep their flex-row layout and are excluded. */
.ipmx-portal__form--event label:not(.ipmx-portal__item),
.ipmx-portal__form--scope label:not(.ipmx-portal__item),
.ipmx-portal__event-docs .ipmx-portal__form label:not(.ipmx-portal__item) {
	display: block;
}

.ipmx-portal__form--event input[type="text"],
.ipmx-portal__form--event input[type="date"],
.ipmx-portal__form--event select,
.ipmx-portal__form--scope select,
.ipmx-portal__event-docs .ipmx-portal__form input[type="text"],
.ipmx-portal__event-docs .ipmx-portal__form input[type="date"] {
	display: block;
	margin-top: 0.3rem;
}

.ipmx-portal input:focus,
.ipmx-portal select:focus,
.ipmx-portal textarea:focus {
	outline: none;
	border-color: var(--ipmx-accent);
	box-shadow: 0 0 0 3px rgba(0, 125, 143, 0.15);
}

.ipmx-portal input:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

/* Buttons (primary teal) */
.ipmx-portal input[type="submit"],
.ipmx-portal button,
.ipmx-portal .button {
	display: inline-block;
	padding: 0.55rem 1.1rem;
	border: 0;
	border-radius: 8px;
	background: var(--ipmx-accent);
	color: #fff;
	font-family: inherit;
	font-weight: 600;
	text-decoration: none;
	cursor: pointer;
	transition: background 0.15s ease;
}

.ipmx-portal input[type="submit"]:hover,
.ipmx-portal button:hover,
.ipmx-portal .button:hover {
	background: var(--ipmx-accent-bright);
}

/* Destructive actions (withdraw / delete) read as a quiet danger style. */
.ipmx-portal__danger input[type="submit"],
.ipmx-portal__danger button {
	background: var(--ipmx-surface);
	color: #b42318;
	border: 1px solid #f3c0bb;
}

.ipmx-portal__danger input[type="submit"]:hover,
.ipmx-portal__danger button:hover {
	background: #fef3f2;
}

/* Notices */
.ipmx-portal__notice {
	margin: 0 0 1rem;
	padding: 0.6rem 0.85rem;
	border: 1px solid var(--ipmx-line);
	border-radius: 8px;
}

.ipmx-portal__notice--ok {
	background: #e6f4f6;
	border-color: #b8e0e6;
	color: #00606e;
}

.ipmx-portal__notice--error {
	background: #fef3f2;
	border-color: #f3c0bb;
	color: #b42318;
}

.ipmx-portal__form {
	margin: 0.85rem 0;
}

.ipmx-portal__form--inline {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	margin: 0;
}

/* "Items under test" / "Profiles & capabilities under test" checkbox groups — the
   event test-scope editor and the vendor add-product form — render as a vertical
   list mirroring the directory's vendor/category filter facets (.ipmx-facet),
   rather than a horizontal run of inline labels. */
.ipmx-portal__items {
	border: 0;
	margin: 0.35rem 0 0;
	padding: 0;
}

.ipmx-portal__items legend {
	margin-bottom: 0.55rem;
	padding: 0;
	font-size: 0.78rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--ipmx-muted);
}

.ipmx-portal__item {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin: 0 0 0.45rem;
	font-size: 0.9rem;
	cursor: pointer;
}

.ipmx-portal__item input[type="checkbox"] {
	flex: 0 0 auto;
	margin: 0;
}

/* A profile-mode sits indented under its parent profile. */
.ipmx-portal__item--mode {
	display: block;
	margin-left: 1.5rem;
}

/* WP-native login form, rendered as a centered brand card. */
.ipmx-portal #loginform {
	max-width: 380px;
	margin: 1.25rem 0 0;
	padding: 1.5rem;
	border: 1px solid var(--ipmx-line);
	border-radius: var(--ipmx-radius);
	background: var(--ipmx-surface);
	box-shadow: 0 6px 24px rgba(16, 24, 40, 0.06);
}

.ipmx-portal #loginform p {
	margin: 0 0 1rem;
}

.ipmx-portal #loginform label {
	display: block;
	margin-bottom: 0.3rem;
	font-weight: 600;
}

.ipmx-portal #loginform .input {
	width: 100%;
}

.ipmx-portal #loginform .login-remember label {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	font-weight: 400;
}

.ipmx-portal #loginform .login-submit {
	margin-bottom: 0;
}

.ipmx-portal #loginform .login-submit input[type="submit"] {
	width: 100%;
}

/* =========================================================================
   Vendor portal — directory preview (bead 2io). Shows the product's card
   exactly as it reads in the public directory, switchable grid/list, with the
   grid thumbnail as an image drop target.
   ========================================================================= */
.ipmx-portal__preview {
	margin: 1.5rem 0 2rem;
}

.ipmx-portal__preview-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	margin-bottom: 0.5rem;
}

.ipmx-portal__preview-head h3 {
	margin: 0;
}

/* Preview card beside the image-spec guidance (wraps on narrow screens). The
   stage hugs the card so the tips sit right next to it, only wrapping below once
   they genuinely run out of room. */
.ipmx-portal__preview-layout {
	display: flex;
	flex-wrap: wrap;
	align-items: start;
	gap: 0.75rem 1rem;
}

.ipmx-portal__preview-stage {
	flex: 0 1 auto;
	margin: 0;
}

/* List view needs real width for the horizontal card; grid hugs its single card. */
.ipmx-portal__preview-stage.ipmx-directory__results--list {
	flex: 1 1 360px;
	min-width: 300px;
}

.ipmx-portal__preview-specs {
	flex: 1 1 220px;
	min-width: 200px;
	font-size: 0.85rem;
	color: var(--ipmx-muted);
}

.ipmx-portal__preview-specs h4 {
	margin: 0 0 0.45rem;
	color: var(--ipmx-ink);
	font-size: 0.92rem;
}

.ipmx-portal__preview-specs ul {
	margin: 0;
	padding-left: 1.1rem;
	display: flex;
	flex-direction: column;
	gap: 0.45rem;
}

/* Image-background picker (grey / white / black) with a live swatch per option. */
.ipmx-portal__bg-picker {
	border: 0;
	margin: 0 0 1rem;
	padding: 0;
}

.ipmx-portal__bg-picker legend {
	padding: 0;
	font-weight: 600;
}

.ipmx-portal__bg-options {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem 1.1rem;
	margin-top: 0.45rem;
}

.ipmx-portal__bg-option {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	cursor: pointer;
}

.ipmx-portal__bg-option span::before {
	content: "";
	display: inline-block;
	width: 15px;
	height: 15px;
	margin-right: 0.3rem;
	border-radius: 3px;
	vertical-align: -2px;
	border: 1px solid var(--ipmx-line);
}

.ipmx-portal__bg-option--grey span::before {
	background: linear-gradient(135deg, #4b515b, #2e333a);
}

.ipmx-portal__bg-option--white span::before {
	background: #fff;
}

.ipmx-portal__bg-option--black span::before {
	background: #0c0d0f;
}

/* None: a frameless choice — a transparent swatch with a diagonal strike so it
   reads as "no field" rather than an empty box. */
.ipmx-portal__bg-option--none span::before {
	background: linear-gradient(
		to top right,
		transparent calc(50% - 1px),
		var(--ipmx-line) calc(50% - 1px),
		var(--ipmx-line) calc(50% + 1px),
		transparent calc(50% + 1px)
	);
}

.ipmx-portal__preview-toggle {
	display: inline-flex;
	border: 1px solid var(--ipmx-line);
	border-radius: 999px;
	overflow: hidden;
}

.ipmx-portal__preview-toggle button {
	margin: 0;
	border: 0;
	background: var(--ipmx-surface);
	color: var(--ipmx-muted);
	padding: 0.35rem 0.95rem;
	font-family: inherit;
	font-size: 0.85rem;
	font-weight: 600;
	cursor: pointer;
}

.ipmx-portal__preview-toggle button.is-active {
	background: var(--ipmx-accent);
	color: #fff;
}

/* A single card in grid view sits at a realistic card width, not stretched. */
.ipmx-portal__preview-stage.ipmx-directory__results--grid {
	grid-template-columns: minmax(240px, 280px);
	justify-content: start;
}

/* Drop affordance (JS adds --droppable): the grid thumb invites an image drop. */
.ipmx-card__thumb--droppable {
	position: relative;
	cursor: copy;
	outline: 2px dashed transparent;
	outline-offset: -6px;
	transition: outline-color 0.15s ease;
}

.ipmx-card__thumb--droppable:hover,
.ipmx-card__thumb--droppable.is-dragover {
	outline-color: var(--ipmx-accent);
}

.ipmx-card__thumb--droppable.is-uploading {
	opacity: 0.6;
}

.ipmx-card__drop-hint {
	position: absolute;
	left: 50%;
	bottom: 8px;
	transform: translateX(-50%);
	max-width: calc(100% - 16px);
	padding: 0.2rem 0.55rem;
	border-radius: 6px;
	background: rgba(17, 20, 24, 0.72);
	color: #fff;
	font-size: 0.72rem;
	white-space: nowrap;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.15s ease;
}

.ipmx-card__thumb--droppable:hover .ipmx-card__drop-hint,
.ipmx-card__thumb--droppable.is-dragover .ipmx-card__drop-hint {
	opacity: 1;
}

/* =========================================================================
   Company-logo section (bead l7u): an in-context preview of the logo as it
   reads beside the vendor name on a listing, so the None/Grey/White/Black
   frame picker shows its effect live. Reuses the directory card's logo chip.
   ========================================================================= */
.ipmx-portal__logo-preview {
	display: inline-flex;
	align-items: center;
	gap: 0.65rem;
	margin: 0.35rem 0 0.85rem;
	padding: 0.7rem 0.9rem;
	border: 1px solid var(--ipmx-line);
	border-radius: var(--ipmx-radius);
	background: var(--ipmx-surface);
}

.ipmx-portal__logo-preview .ipmx-card__vendor-logo img {
	max-height: 34px;
}

.ipmx-portal__logo-preview-name {
	font-weight: 600;
}

.ipmx-portal__logo-preview-empty {
	color: var(--ipmx-muted);
	font-size: 0.9rem;
}

/* =========================================================================
   Product-image manager folded under the directory preview (bead 7m6): a strip
   of thumbnails to add more, choose the main image (click), and remove (×).
   Every control is a real form, so it works with no JS; this is a compact
   restyle of the old standalone media section.
   ========================================================================= */
.ipmx-portal__media {
	margin: 0.5rem 0 0.5rem;
}

.ipmx-portal__media-head {
	margin: 0 0 0.35rem;
	font-size: 0.92rem;
	font-weight: 600;
}

.ipmx-portal__media-strip {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	/* Top-align so the taller "add" tile (label + no-JS Upload button) never
	   stretches the square image thumbs. */
	align-items: flex-start;
}

.ipmx-portal__media-thumb {
	position: relative;
	width: 84px;
	height: 84px;
	border-radius: 8px;
	overflow: hidden;
	border: 1px solid var(--ipmx-line);
	background: var(--ipmx-image-field);
}

.ipmx-portal__media-thumb img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	display: block;
}

/* The thumbnail itself is the make-main-image control (a borderless button). */
.ipmx-portal__media-pick {
	display: block;
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
}

.ipmx-portal__media-thumb--primary {
	border-color: var(--ipmx-accent);
	box-shadow: 0 0 0 1px var(--ipmx-accent);
}

.ipmx-portal__media-thumb--primary .ipmx-portal__media-pick {
	cursor: default;
}

.ipmx-portal__media-badge {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 0.1rem 0.3rem;
	font-size: 0.6rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-align: center;
	background: var(--ipmx-accent);
	color: #fff;
}

.ipmx-portal__media-strip .ipmx-portal__form--inline {
	margin: 0;
}

.ipmx-portal__media-remove {
	position: absolute;
	top: 3px;
	right: 3px;
	width: 20px;
	height: 20px;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: rgba(17, 20, 24, 0.74);
	color: #fff;
	font-size: 0.82rem;
	line-height: 18px;
	text-align: center;
	cursor: pointer;
}

.ipmx-portal__media-remove:hover {
	background: var(--ipmx-danger, #b42318);
}

/* The "add" tile reuses the upload form, shown as a dashed click/drop target. It
   is a flex column that GROWS to fit the label + the no-JS Upload button (the
   strip is top-aligned, so a taller tile never stretches the image thumbs). */
.ipmx-portal__media-add {
	width: 84px;
	min-height: 84px;
	border: 1px dashed var(--ipmx-line);
	border-radius: 8px;
	display: flex;
}

.ipmx-portal__media-add .ipmx-portal__form {
	margin: 0;
	width: 100%;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 0.3rem;
	padding: 0.4rem;
	box-sizing: border-box;
}

.ipmx-portal__media-add-label {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.1rem;
	cursor: pointer;
	color: var(--ipmx-muted);
	font-size: 0.74rem;
	line-height: 1.1;
	text-align: center;
}

.ipmx-portal__media-add-label::before {
	content: "+";
	font-size: 1.4rem;
	line-height: 1;
	color: var(--ipmx-accent);
}

/* The file input is visually hidden but reachable — the label opens the dialog
   and JS auto-submits on change. The Upload button is the no-JS fallback; the
   portal script hides it once the auto-submit is wired. */
.ipmx-portal__media-add input[type="file"] {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
}

.ipmx-portal__media-add .ipmx-portal__media-add-submit {
	display: block;
	width: 100%;
	margin: 0;
	padding: 0.3rem 0.2rem;
	font-size: 0.7rem;
}

/* =========================================================================
   Shareable "filter the registry to my products" link (bead t9h): a read-only
   URL + copy button in the portal editor, and the dismissible "Showing only
   <Vendor>" chip on the public directory.
   ========================================================================= */
.ipmx-portal__share {
	margin: 0 0 0.85rem;
}

.ipmx-portal__share-row {
	display: flex;
	gap: 0.5rem;
	align-items: stretch;
	max-width: 560px;
	margin-top: 0.35rem;
}

.ipmx-portal__share-url {
	flex: 1 1 auto;
	min-width: 0;
	/* Fill the row (override the short-input cap); monospace reads as a URL. */
	max-width: none;
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: 0.85rem;
}

.ipmx-portal__copy {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	white-space: nowrap;
}

.ipmx-portal__copy-icon {
	font-size: 1.05rem;
	line-height: 1;
}

.ipmx-portal__copy.is-copied {
	background: var(--ipmx-accent-bright);
}

/* Active-filter pills on the public archive: the collapsed-panel view of what is
   filtered. Hidden by default; shown only when JS is present AND the panel is
   collapsed, so opening the panel swaps the pills for the checked checkboxes and
   no-JS visitors see only the boxes. */
.ipmx-directory__active-filters {
	display: none;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem 0.75rem;
	margin: 0 0 1rem;
}

.ipmx-has-js .ipmx-filters:not(.is-expanded) ~ .ipmx-directory__main .ipmx-directory__active-filters {
	display: flex;
}

.ipmx-active-filters__label {
	font-size: 0.8rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--ipmx-muted);
}

.ipmx-active-filters__list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ipmx-filter-chip {
	/* --chip-color is set per dimension below; default to the brand accent. */
	--chip-color: var(--ipmx-accent);
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	padding: 0.3rem 0.35rem 0.3rem 0.7rem;
	border: 1px solid var(--ipmx-line);
	border-radius: 999px;
	background: var(--ipmx-bg-soft);
	font-size: 0.9rem;
	color: var(--ipmx-ink);
}

.ipmx-filter-chip__dot {
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--chip-color);
	flex: 0 0 auto;
}

/* Colour-coded by dimension (subtle: the dot + the × hover carry the colour). */
.ipmx-filter-chip--tier {
	--chip-color: #0e9f6e;
}

.ipmx-filter-chip--profile {
	--chip-color: #2563eb;
}

.ipmx-filter-chip--profile-mode {
	--chip-color: #0891b2;
}

.ipmx-filter-chip--capability {
	--chip-color: #d97706;
}

.ipmx-filter-chip--category {
	--chip-color: #6366f1;
}

.ipmx-filter-chip--vendor {
	--chip-color: #c026d3;
}

.ipmx-filter-chip__clear {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: var(--ipmx-line);
	color: var(--ipmx-ink);
	text-decoration: none;
	font-size: 1rem;
	line-height: 1;
}

.ipmx-filter-chip__clear:hover,
.ipmx-filter-chip__clear:focus {
	background: var(--chip-color);
	color: #fff;
}

/* =========================================================================
   Surface strip (bead 6wli): under the site-chrome theme the host logo and
   navigation belong to the theme, so the brand band shrinks to the surface
   name on the brand underline.
   ========================================================================= */
.ipmx-brand--strip {
	gap: 0;
	margin: 1.6rem 0 1.5rem;
	padding-bottom: 0.7rem;
}

.ipmx-brand__subtitle--strip {
	font-size: 1.35rem;
	font-weight: 700;
	letter-spacing: 0.005em;
}

/* =========================================================================
   Detail gallery image field (bead kz49): the product's own background choice,
   white by default, mirroring the directory-card variants above.
   ========================================================================= */
.ipmx-detail__gallery[data-ipmx-img-bg="white"] .ipmx-gallery__slide img,
.ipmx-detail__gallery[data-ipmx-img-bg="white"] .ipmx-detail__noimage {
	--ipmx-image-field: #ffffff;
	background-color: #ffffff;
	box-shadow: inset 0 0 0 1px rgba(17, 20, 24, 0.07), 0 1px 4px rgba(0, 0, 0, 0.12);
}

.ipmx-detail__gallery[data-ipmx-img-bg="black"] .ipmx-gallery__slide img,
.ipmx-detail__gallery[data-ipmx-img-bg="black"] .ipmx-detail__noimage {
	--ipmx-image-field: #0c0d0f;
	background-color: #0c0d0f;
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 1px 4px rgba(0, 0, 0, 0.22);
}

.ipmx-detail__gallery[data-ipmx-img-bg="none"] .ipmx-gallery__slide img {
	--ipmx-image-field: transparent;
	background: transparent;
	box-shadow: none;
	padding: 0;
}

.ipmx-detail__gallery[data-ipmx-img-bg="none"] .ipmx-detail__noimage {
	background-color: transparent;
	box-shadow: none;
}
