/*
 * Default styling for the markup [cms] and the fallback templates emit.
 *
 * This lived in divi-child/style.css, which is where site CSS belongs -- but
 * these classes are emitted by this plugin, not by the theme, so a theme change
 * left every listing that has no Divi card layout unstyled. The three
 * collections without one (Conditions, Resources, Investigator Profiles) are
 * exactly the ones that could least afford it.
 *
 * A theme still wins: this is enqueued before the theme's stylesheet, so any
 * rule in style.css with equal specificity overrides it.
 */

/*
 * Every colour and measurement this stylesheet uses, in one place.
 *
 * They live on :root rather than on .cms-filters, which is where they started,
 * because the accent is not the filter bar's -- it is the plugin's. The
 * pagination's current page was a hard-coded green while the bar a few pixels
 * above it was the client's purple, which is the kind of mismatch nobody
 * reports and everybody sees.
 *
 * --cms-accent is overwritten inline from Divi's own accent_color at render
 * time (CMS_Filters::accent()), so everything the plugin draws is the site's
 * brand colour on day one and follows it when the client changes it in the
 * ePanel. A site that wants something else overrides one line in Divi's
 * Custom CSS box:
 *
 *     :root { --cms-accent: #15c586; }
 */
:root {
	--cms-accent: #2ea3f2;
	--cms-ink: #2b2b2b;
	--cms-muted: rgba(0, 0, 0, 0.52);
	--cms-line: rgba(0, 0, 0, 0.13);
	--cms-field: #fff;
	--cms-tint: rgba(0, 0, 0, 0.045);
	/* Divi's own controls sit at 3px, so the fields follow that rather than
	 * the fully-round shape the pills use -- a filter field is the same kind
	 * of object as the theme's other inputs, and a tag is not. */
	--cms-radius: 4px;

	/* The shape every card's image is cropped to, and how many lines its
	 * summary is allowed. Both are properties rather than literals so a site
	 * with taller artwork can retune the whole grid from Divi's Custom CSS box
	 * without touching a plugin file. */
	--cms-card-ratio: 3 / 2;
	--cms-card-lines: 3;
	--cms-card-title-lines: 3;
	--cms-card-gap: 24px;
}

/* The wrapper around all entries */
.cms-list {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	gap: var(--cms-card-gap);
	/* Grid stretches a row's items to its tallest by default, and the carded
	 * rules below lean on that: a card is a full-height flex column, so its
	 * button lands on the same line as every other card's in the row. */
	align-items: stretch;
	margin: 0 0 24px;
}

/* One entry */
.cms-entry {
	background: #fff;
	border: 1px solid #e5e5e5;
	border-radius: 8px;
	padding: 24px;
	box-shadow: 0 2px 6px rgba(0, 0, 0, .05);
}

.cms-entry__title {
	margin: 0 0 12px;
	font-size: 20px;
	line-height: 1.3;
}

/* One field inside an entry */
.cms-field {
	margin-bottom: 12px;
}

.cms-field:last-child {
	margin-bottom: 0;
}

/* The small grey label above each value. */
.cms-field__label {
	display: block;
	font-size: 12px;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: #888;
	margin-bottom: 4px;
}

.cms-field__value {
	line-height: 1.6;
}

/* Images */
.cms-image {
	max-width: 100%;
	height: auto;
	border-radius: 6px;
}

/* Repeater rows */
.cms-rows {
	list-style: none;
	margin: 0;
	padding: 0;
}

.cms-row {
	padding: 4px 0;
}

.cms-row .cms-sub {
	margin-right: 10px;
}

/*
 * A reference whose target has not been imported yet.
 *
 * It renders as readable text rather than a link, on purpose -- see the
 * reference notes in CLAUDE.md. Giving it a muted colour makes the difference
 * visible to an editor without making it look broken to a reader.
 */
.cms-ref-missing {
	color: #6b7280;
}

/* --------------------------------------------------------------------------
   Fixed column counts: [cms section="conditions" columns="3"]
   --------------------------------------------------------------------------

   The rule above is the default and is usually the better answer: the browser
   fits as many 280px tiles as the space allows, and nothing needs re-tuning
   when the container width changes.

   These are for when the design calls for a specific count -- three across on
   a hub page, two beside a sidebar. They need explicit breakpoints, which is
   the reason this is a class rather than an inline style: a fixed four-across
   is four across on a desktop and must fall back on a phone, and an inline
   grid-template-columns cannot say that.
   -------------------------------------------------------------------------- */

.cms-list--cols-1 { grid-template-columns: 1fr; }
.cms-list--cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cms-list--cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cms-list--cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.cms-list--cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.cms-list--cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }

/* Tablet: nothing wider than three across survives, so step everything down. */
@media (max-width: 1100px) {
	.cms-list--cols-4,
	.cms-list--cols-5,
	.cms-list--cols-6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 840px) {
	.cms-list--cols-3,
	.cms-list--cols-4,
	.cms-list--cols-5,
	.cms-list--cols-6 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Phone: one card across, whatever was asked for. */
@media (max-width: 560px) {
	.cms-list { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   A carded listing: one Divi layout repeated per entry
   --------------------------------------------------------------------------

   The card is a Divi Library layout, so what is inside it is the client's to
   design and none of it is styled here. What IS here is the one thing a
   library layout cannot know: that it is being repeated, and has to line up
   with twenty-three others.

   Two measurements, taken across all four listings on both installs, are what
   these rules answer:

   - the entries' images run from 0.56 to 1.92 in aspect ratio, because they
     are photographs the client uploaded rather than artwork cut to a grid. One
     portrait photograph in a three-across row set the height of the whole row
     and left the two cards beside it sitting under a hole.
   - their summaries run from 37 to 554 characters, so "Read more" landed at a
     different height in every card.

   Neither is a fault in the layout, and neither can be fixed by editing one: a
   Divi module has no way to say "the same height as the card beside me".
   -------------------------------------------------------------------------- */

.cms-list--carded > .cms-card {
	display: flex;
	/* A grid item's min-width is auto, which lets one long unbroken word -- a
	 * URL, a drug name -- push its column wider than its share. */
	min-width: 0;
	height: 100%;
}

/*
 * Divi wraps every library layout in section > row > column, and all three
 * have to pass the height down or the button cannot reach the bottom of the
 * card. Their own widths and paddings are written for a full-width page
 * section, which is not what this is: inside a card they put a 20% gutter
 * around a 280px tile.
 *
 * `.cms-card > div` is here because the chain is longer in the browser than it
 * is in the response. Divi's front-end script wraps each rendered layout in
 * `<div id="et-boc"><div class="et-l">` after the page loads -- twenty-four
 * times over, all carrying the same id -- so a rule written against the
 * server's HTML stops matching the moment the page finishes loading. That is
 * what this was: every card measured 390px tall and every button sat at its
 * own height inside one, because two unstyled block wrappers in the middle of
 * a flex chain were absorbing the height before the column could see it.
 * Nothing errored, and the listing looked exactly as it had before the fix.
 */
.cms-list--carded .cms-card > div,
.cms-list--carded .et-l,
.cms-list--carded .et_pb_section,
.cms-list--carded .et_pb_row,
.cms-list--carded .et_pb_column {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	width: 100%;
	max-width: none;
	min-width: 0;
	margin: 0;
	padding: 0;
}

/* Divi floats its columns. Inside a flex row the float is ignored, but the
 * bottom margin it carries for a page layout is not. */
.cms-list--carded .et_pb_column {
	float: none;
}

/* ------------------------------------------------------------- the image */

/*
 * One shape for every card, whatever shape the photograph is.
 *
 * The crop is object-fit rather than a height on the image, so nothing is ever
 * squashed: the frame is 3:2 and the photograph fills it, losing its edges
 * instead of its proportions. The bias above centre is because these are
 * overwhelmingly photographs of people, and a face sits in the upper half of a
 * portrait frame -- a centred crop takes the top of the head off.
 */
.cms-list--carded .et_pb_image {
	width: 100%;
	max-width: 100%;
	margin: 0 0 18px;
}

.cms-list--carded .et_pb_image a,
.cms-list--carded .et_pb_image .et_pb_image_wrap {
	display: block;
	width: 100%;
}

.cms-list--carded .et_pb_image .et_pb_image_wrap {
	position: relative;
	aspect-ratio: var(--cms-card-ratio);
	overflow: hidden;
	border-radius: 8px;
	/* An image still loading leaves the frame behind, not a collapsed card. */
	background: var(--cms-tint);
}

.cms-list--carded .et_pb_image .et_pb_image_wrap img {
	position: absolute;
	top: 0;
	left: 0;
	display: block;
	width: 100%;
	height: 100%;
	max-width: none;
	object-fit: cover;
	object-position: center 35%;
	border-radius: inherit;
}

/* ------------------------------------------------------ title and summary */

.cms-list--carded .et_pb_text {
	margin: 0 0 10px;
}

.cms-list--carded .et_pb_text_inner > :first-child { margin-top: 0; }
.cms-list--carded .et_pb_text_inner > :last-child { margin-bottom: 0; }

.cms-list--carded .et_pb_text_inner h2,
.cms-list--carded .et_pb_text_inner h3,
.cms-list--carded .et_pb_text_inner h4 {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: var(--cms-card-title-lines);
	line-clamp: var(--cms-card-title-lines);
	overflow: hidden;
	padding: 0;
}

/*
 * The summary is clamped and the title is barely, because they fail
 * differently. A title is a name and reads wrong cut short, so it gets three
 * lines it will almost never use. A summary is a taste of the entry, and one
 * card carrying fourteen lines of it beside another carrying one is the thing
 * that makes a grid look broken -- the point of the card is the page behind
 * it.
 */
.cms-list--carded .et_pb_text_inner > p {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: var(--cms-card-lines);
	line-clamp: var(--cms-card-lines);
	overflow: hidden;
}

/* ------------------------------------------------------------ the button */

/*
 * auto is what lines the row up: each button is pushed to the bottom of its
 * own card, and each card is the height of the tallest in its row, so they
 * land on one line without anything having been told how tall to be.
 */
.cms-list--carded .et_pb_button_module_wrapper {
	margin: auto 0 0;
	padding-top: 16px;
}

.cms-list--carded .et_pb_button_module_wrapper .et_pb_button {
	align-self: flex-start;
}

/* ----------------------------------------- the fallback (uncarded) listing

   A section with no cms-card-{handle} layout renders .cms-entry boxes
   instead. They carry their own chrome so they need less than a card does,
   but a row of them has exactly the same two problems. */

.cms-list > .cms-entry {
	display: flex;
	flex-direction: column;
	min-width: 0;
	height: 100%;
}

.cms-list > .cms-entry .cms-image {
	width: 100%;
	aspect-ratio: var(--cms-card-ratio);
	object-fit: cover;
	object-position: center 35%;
}

/* --------------------------------------------------------------------------
   The archive template's own column
   --------------------------------------------------------------------------

   templates/archive-entries.php borrows Divi's page furniture -- #main-content,
   #content-area, #left-area -- so that an archive looks like the rest of the
   theme without the plugin reimplementing a layout. #left-area is 79% wide,
   because Divi expects a sidebar in the remaining fifth, and this template
   prints no sidebar: the listing sat in two thirds of the page with an empty
   third beside it, which reads as a column that failed to load rather than as
   a design.

   Divi's own rule is an id, so this needs the class in front of it to win.
   -------------------------------------------------------------------------- */

.cms-archive #left-area {
	width: 100%;
	max-width: none;
	padding-right: 0;
	float: none;
}

.cms-archive__header {
	margin: 0 0 26px;
}

/* Divi draws the rule between content and sidebar as a border on the
 * container's own ::before, so it is still there on a page with no sidebar --
 * a full-height vertical line down the right-hand third of the listing, with
 * nothing on either side of it. */
.cms-archive__container::before {
	display: none;
}

/* --------------------------------------------------------------------------
   Pagination
   -------------------------------------------------------------------------- */

.cms-pagination {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	justify-content: center;
	margin: 32px 0 8px;
}

.cms-pagination .page-numbers {
	display: inline-block;
	padding: 8px 14px;
	border: 1px solid #d9e0dd;
	border-radius: 6px;
	line-height: 1.2;
	text-decoration: none;
}

.cms-pagination .page-numbers.current {
	/* The site's colour, not a green chosen here: this sits directly under a
	 * filter bar drawn in Divi's accent, and two different brand colours a few
	 * pixels apart is the tell that a plugin drew one of them. */
	background: var(--cms-accent);
	border-color: var(--cms-accent);
	color: #fff;
}

.cms-pagination .page-numbers:not(.current):not(.dots):hover {
	border-color: var(--cms-accent);
	color: var(--cms-accent);
}

.cms-pagination .page-numbers.dots {
	border-color: transparent;
}

/* --------------------------------------------------------------------------
   A field block written by [cms_field field="x" heading="..."]
   -------------------------------------------------------------------------- */

.cms-block + .cms-block {
	margin-top: 28px;
}

.cms-block__heading {
	margin: 0 0 10px;
}

/* ---------------------------------------------------------------- filters */

/*
 * The filter bar.
 *
 * It ships with the plugin rather than the theme for the same reason the
 * listing grid does: the classes come from the plugin, so a theme switch or a
 * Divi update must not take the styling with it.
 *
 * Three rules run through all of it, and all three are about belonging to
 * whatever page it lands on rather than announcing itself:
 *
 * 1. **No font is set.** The bar inherits the theme's -- Roboto on the client's
 *    install, whatever the next site uses on the next one. The first version
 *    set its own, and that alone made it read as a plugin bolted onto the page.
 *
 * 2. **No panel.** No background, no box, no shadow. A Divi page is built from
 *    airy full-width sections, and a bordered grey card dropped into one looks
 *    like a widget. The bar is separated from the results by a single hairline
 *    instead, which is how the rest of the page separates things.
 *
 * 3. **Every colour is a custom property**, and --cms-accent is written inline
 *    from Divi's own accent_color at render time -- so the bar is the client's
 *    brand on day one (#6a2b7f here) and Divi's blue on a default install, from
 *    this one file with nothing hard-coded either side. A site that wants
 *    something else overrides one line in Divi's Custom CSS box.
 */

.cms-filters {
	/* The tokens are on :root now, so the bar inherits them the way everything
	 * else the plugin draws does. A .cms-filters override in Divi's Custom CSS
	 * box still wins inside the bar, which is what the old note here promised.
	 */

	/* The theme's body size is the page's, not this component's: the client's
	 * is 14px, and an 0.85em label off that base lands at 11.9px, which is
	 * below what anyone should have to read a control at. Setting a base here
	 * lets every size below stay relative and still land somewhere sensible. */
	font-size: 15px;
	line-height: 1.5;
	margin: 0 0 22px;
}

.cms-filters__title {
	margin: 0 0 14px;
	font-size: 1.05em;
	font-weight: 600;
	line-height: 1.3;
	color: var(--cms-ink);
}

/* ------------------------------------------------------- the top row */

.cms-filters__controls {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 14px;
}

/* The search box takes the room going spare and the sort control does not, so
 * the row reads left to right as "what am I looking for", then "in what
 * order" -- and on a narrow screen the search box is the one that stays wide. */
.cms-filters__search {
	position: relative;
	flex: 1 1 260px;
	min-width: 0;
	max-width: 420px;
}

.cms-filters__icon {
	position: absolute;
	top: 50%;
	left: 13px;
	transform: translateY(-50%);
	opacity: 0.38;
	pointer-events: none;
}

.cms-filters__search input[type="search"] {
	width: 100%;
	max-width: 100%;
	height: 44px;
	margin: 0;
	padding: 0 15px 0 39px;
	border: 1px solid var(--cms-line);
	border-radius: var(--cms-radius);
	background: var(--cms-field);
	font: inherit;
	font-size: 0.95em;
	line-height: 1.4;
	color: var(--cms-ink);
	/* Safari draws a magnifier and an inner shadow of its own on this type. */
	-webkit-appearance: none;
	appearance: none;
	box-shadow: none;
}

.cms-filters__search input[type="search"]::placeholder {
	color: var(--cms-muted);
	opacity: 1;
}

.cms-filters__field {
	display: flex;
	flex: 0 1 auto;
	align-items: center;
	gap: 9px;
	min-width: 0;
	margin: 0;
}

.cms-filters__field label {
	flex: none;
	font-size: 0.86em;
	line-height: 1.3;
	white-space: nowrap;
	color: var(--cms-muted);
}

.cms-filters__field select {
	width: auto;
	max-width: 230px;
	height: 44px;
	margin: 0;
	padding: 0 34px 0 14px;
	border: 1px solid var(--cms-line);
	border-radius: var(--cms-radius);
	background-color: var(--cms-field);
	/* The native arrow sits at a different offset in every browser and cannot
	 * be positioned; drawing our own is the only way this control lines up
	 * with the search box beside it. */
	background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%23666' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 13px center;
	font: inherit;
	font-size: 0.93em;
	line-height: 1.4;
	color: var(--cms-ink);
	text-overflow: ellipsis;
	-webkit-appearance: none;
	appearance: none;
	cursor: pointer;
}

/* The sort control belongs at the far end of the row, away from the things
 * that narrow the listing -- it does not narrow anything. */
.cms-filters__field--sort {
	margin-left: auto;
}

.cms-filters__search input[type="search"]:focus,
.cms-filters__field select:focus {
	border-color: var(--cms-accent);
	outline: 2px solid var(--cms-accent);
	outline-offset: 1px;
}

.cms-filters__actions {
	display: flex;
	align-items: center;
	gap: 14px;
	margin: 0;
}

.cms-filters__apply {
	height: 44px;
	padding: 0 22px;
	border: 0;
	border-radius: var(--cms-radius);
	background: var(--cms-accent);
	font: inherit;
	font-size: 0.93em;
	font-weight: 500;
	line-height: 1;
	color: #fff;
	cursor: pointer;
}

.cms-filters__clear {
	font-size: 0.88em;
	color: var(--cms-muted);
	text-decoration: underline;
}

/*
 * Apply has nothing to do once the controls submit themselves, and it is still
 * the submit button a keyboard user reaches by pressing Enter in the search
 * box -- so it is hidden visually and never removed.
 *
 * Hidden by DEFAULT, and restored by a <noscript> rule in the bar itself. It
 * used to be hidden by a class the script added, and the script is in the
 * footer: on a hard refresh the button was painted with the bar and taken away
 * a moment later, which is a control that appears and then vanishes. Doing it
 * this way round means the no-JavaScript case is the one that needs a rule,
 * and no rendering depends on when a script runs.
 */
.cms-filters__apply {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	border: 0;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
}

.cms-filters--live .cms-filters__actions:not(:has(.cms-filters__clear)) {
	display: none;
}

.cms-filters__form.is-loading {
	opacity: 0.5;
	pointer-events: none;
	transition: opacity 0.12s ease-out;
}

/* ------------------------------------------------------------ the pills */

/*
 * The primary facet, drawn as links rather than as a dropdown.
 *
 * A `<select>` hides its own contents, and on a listing whose whole
 * proposition is "browse by condition" those twenty-two conditions are the
 * most useful thing on the page. Links also mean the row needs no JavaScript,
 * takes the keyboard for free, and gives every choice a real URL.
 */
.cms-filters__pills {
	display: flex;
	flex-wrap: nowrap;
	gap: 8px;
	margin: 0;
	padding: 2px;
	/* One line that scrolls, not four that wrap: twenty-two wrapped pills push
	 * the listing itself below the fold. */
	overflow-x: auto;
	/*
	 * And no native scrollbar under it.
	 *
	 * `thin` is not thin on Windows: Chrome draws a full-width grey trough
	 * with an arrow at each end, and under a row of pills that reads as a
	 * scrollbar belonging to the page rather than to the row. It was the
	 * single least finished-looking thing on the listing. What replaces it is
	 * the fade below plus the two round buttons the script adds, which say the
	 * same thing in the component's own language -- and a touch screen, which
	 * is where most of this scrolling happens, never drew one anyway.
	 */
	scrollbar-width: none;
	-ms-overflow-style: none;
	-webkit-overflow-scrolling: touch;
	scroll-snap-type: x proximity;
}

.cms-filters__pills::-webkit-scrollbar {
	width: 0;
	height: 0;
}

/*
 * The rail is the script's doing: it wraps the row so the two nudge buttons
 * have something to be positioned against. Wrapped in JavaScript rather than
 * printed by PHP because a button that scrolls a row is worth nothing without
 * JavaScript, and markup for a control that cannot work is worse than none.
 */
.cms-filters__rail {
	position: relative;
	margin: 14px 0 0;
}

.cms-filters__nudge {
	position: absolute;
	top: 50%;
	z-index: 2;
	display: none;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	margin: 0;
	padding: 0;
	transform: translateY(-50%);
	border: 1px solid var(--cms-line);
	border-radius: 999px;
	background: var(--cms-field);
	font: inherit;
	line-height: 1;
	color: var(--cms-ink);
	box-shadow: 0 1px 5px rgba(0, 0, 0, 0.12);
	cursor: pointer;
	transition: opacity 0.14s ease-out, border-color 0.14s ease-out;
}

.cms-filters__rail.has-overflow .cms-filters__nudge { display: flex; }

.cms-filters__nudge:hover { border-color: var(--cms-accent); }

.cms-filters__nudge:focus-visible {
	outline: 2px solid var(--cms-accent);
	outline-offset: 2px;
}

/* Hidden rather than greyed once the row is at its end: a disabled button that
 * stays put is a control that looks broken. */
.cms-filters__nudge[disabled] {
	opacity: 0;
	pointer-events: none;
}

.cms-filters__nudge--prev { left: -6px; }
.cms-filters__nudge--next { right: -6px; }

.cms-filters__nudge svg {
	display: block;
	width: 15px;
	height: 15px;
}

/* A touch screen scrolls the row by swiping, and has no cursor to put on a
 * 34px target. */
@media (hover: none), (pointer: coarse) {
	.cms-filters__rail.has-overflow .cms-filters__nudge { display: none; }
}

/*
 * The row must look cut off rather than finished, or nobody scrolls it -- but
 * only when there is something past the edge. The class comes from the script,
 * which measures the row; applying the fade unconditionally faded the last pill
 * on Investigator Profiles, which has five and fits.
 */
.cms-filters__pills.has-overflow {
	-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 44px), transparent);
	mask-image: linear-gradient(to right, #000 calc(100% - 44px), transparent);
}

.cms-filters__pills.has-overflow.is-scrolled {
	-webkit-mask-image: linear-gradient(to right, transparent, #000 30px, #000 calc(100% - 44px), transparent);
	mask-image: linear-gradient(to right, transparent, #000 30px, #000 calc(100% - 44px), transparent);
}

.cms-filters__pills.has-overflow.is-end {
	-webkit-mask-image: linear-gradient(to right, transparent, #000 30px);
	mask-image: linear-gradient(to right, transparent, #000 30px);
}

.cms-pill {
	display: inline-flex;
	flex: none;
	align-items: center;
	gap: 7px;
	padding: 8px 14px;
	border: 1px solid var(--cms-line);
	border-radius: 999px;
	background: var(--cms-field);
	font-size: 0.9em;
	line-height: 1.35;
	white-space: nowrap;
	color: var(--cms-ink);
	text-decoration: none;
	scroll-snap-align: start;
	transition: border-color 0.14s ease-out, background-color 0.14s ease-out, color 0.14s ease-out;
}

.cms-pill:hover,
.cms-pill:focus {
	border-color: var(--cms-accent);
	background: var(--cms-tint);
	color: var(--cms-ink);
	text-decoration: none;
}

.cms-pill:focus-visible {
	outline: 2px solid var(--cms-accent);
	outline-offset: 2px;
}

.cms-pill.is-active {
	border-color: var(--cms-accent);
	background: var(--cms-accent);
	color: #fff;
}

.cms-pill__n {
	padding: 1px 7px;
	border-radius: 999px;
	background: var(--cms-tint);
	font-size: 0.86em;
	font-variant-numeric: tabular-nums;
	line-height: 1.55;
	color: var(--cms-muted);
}

.cms-pill.is-active .cms-pill__n {
	background: rgba(255, 255, 255, 0.24);
	color: #fff;
}

/* --------------------------------------------------------- the summary */

/*
 * The hairline under this is what separates the controls from the results.
 * There is no box around the bar, so this is the only thing that says where
 * one ends and the other begins -- and one rule does it on all four listings,
 * including the two whose bar is a search box and a sort control with no pills
 * under it.
 */
.cms-summary {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 14px;
	margin: 16px 0 22px;
	padding: 0 0 14px;
	border-bottom: 1px solid rgba(0, 0, 0, 0.1);
	font-size: 15px;
	line-height: 1.5;
}

.cms-summary__count {
	margin: 0;
	font-size: 0.88em;
	letter-spacing: 0.01em;
	color: rgba(0, 0, 0, 0.55);
}

.cms-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.cms-chips__item {
	margin: 0;
	padding: 0;
	list-style: none;
}

.cms-chip {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 4px 12px;
	border: 1px solid rgba(0, 0, 0, 0.12);
	border-radius: 999px;
	background: rgba(0, 0, 0, 0.03);
	font-size: 0.85em;
	line-height: 1.5;
	color: inherit;
	text-decoration: none;
}

.cms-chip:hover,
.cms-chip:focus {
	border-color: rgba(0, 0, 0, 0.35);
	text-decoration: none;
}

.cms-chip__label { opacity: 0.5; }
.cms-chip__value { font-weight: 600; }

.cms-chip__x {
	font-size: 1.2em;
	line-height: 1;
	opacity: 0.45;
}

.cms-chip--clear {
	border-style: dashed;
	background: none;
	font-weight: 600;
}

/* ------------------------------------------------------ nothing matched */

.cms-empty {
	margin: 0;
	padding: 44px 24px;
	border: 1px dashed rgba(0, 0, 0, 0.16);
	border-radius: 6px;
	text-align: center;
	color: rgba(0, 0, 0, 0.6);
}

.cms-empty__clear {
	display: inline-block;
	margin-left: 6px;
	font-weight: 600;
	text-decoration: underline;
}

/* The anchor a filter submit jumps to. scroll-margin keeps the bar itself on
 * screen after the jump instead of pinning it to the very top edge, and clears
 * a sticky header while it is at it. */
.cms-results {
	scroll-margin-top: 110px;
}

@media (max-width: 782px) {
	.cms-filters__controls { gap: 10px; }

	.cms-filters__search {
		flex: 1 1 100%;
		max-width: none;
	}

	.cms-filters__field { flex: 1 1 100%; }

	.cms-filters__field select {
		flex: 1 1 auto;
		max-width: none;
	}

	.cms-filters__field--sort { margin-left: 0; }
}

@media (prefers-reduced-motion: reduce) {
	.cms-pill,
	.cms-filters__form { transition: none; }
}
