/*
 * Structure for the filter elements.
 *
 * Every value here is a design token. Nothing is a literal: change --space-s in
 * the builder and these move with the rest of the site. What lives in this file
 * is layout that must be true for the element to work at all, not decoration.
 *
 * It is a stylesheet rather than element control defaults because a Bricks
 * control `default` is a builder convenience, not a rendered value: Bricks
 * generates CSS from an element's SAVED settings, so a default nobody touched
 * emits nothing. Chips shipped invisible that way, and facet options stayed
 * `display: inline`, which also made them invisible to the tap-target gate
 * (WCAG exempts inline links, so check-mobile.js skipped them rather than
 * passing them).
 *
 * The style controls on both elements still win: they emit later and are more
 * specific, so anything set in the builder overrides this file.
 *
 * Buttons, text fields and toggles are NOT here. They are in controls.css, and
 * nothing in this file may restyle one: an element picks .oview-btn or
 * .oview-field and adds only the layout that makes it sit correctly. Five
 * controls in this file had grown five different shapes before that rule
 * existed.
 */

/* --- facet --------------------------------------------------------------
 *
 * A card, the way BuddyBoss builds a sidebar widget: a bordered surface with a
 * title, its content, and its own affordance in the corner. Bare stacked lists
 * were readable but gave no edge to a facet, so four of them read as one long
 * column of unrelated headings.
 */

/* The card itself is .oview-panel in controls.css, shared with the sort. */

/* A search in flight. Deliberately faint: the list is still readable and still
   correct, it is just about to be replaced by a narrower one. */
.oview-facet.is-searching .oview-facet__list {
	opacity: 0.55;
	transition: opacity 120ms ease;
}

/*
 * The same icon inside an OPTION, where it stands in for the checkbox.
 *
 * ⚠️ NO TILE AND NO BORDER. It is the heading icons' treatment, one row down: a
 * bare symbol at the size of the box it replaced, so the column of rows still
 * lines up whether a facet declares icons or not.
 */
.oview-facet__icon--option {
	width: 1.8rem;
	justify-content: center;
	color: var(--color-text-muted);
}

.oview-facet__icon--option svg {
	width: 1.6rem;
	height: 1.6rem;
}

.oview-facet__head {
	display: flex;
	align-items: center;
	gap: var(--space-xs);
}

.oview-facet__label {
	margin: 0;
	/* --text-m, not --text-l. At 18-20px a two-word facet name wrapped in a
	   260px sidebar, and the card titles outweighed the options under them. */
	font-size: var(--text-m);
	font-weight: 600;
	/*
	 * ⚠️ Stated, not inherited. A facet title is an h2 and picks the colour up
	 * from the theme style's heading rule; the sort's is a <label>, which does
	 * not - and something styles a bare label #9e9e9e, so the one panel title
	 * that was not a heading rendered grey beside four dark ones. A panel title
	 * is a panel title whatever tag it is in.
	 */
	color: var(--color-text);
}

/*
 * The facet's icon, muted with the heading rather than coloured: four
 * accent-coloured icons down a sidebar read as four buttons.
 *
 * Sized in em, so it tracks --text-m when that changes instead of needing its
 * own number. currentColor is why the loader rewrites the black these files
 * ship with (Icons::get).
 */
.oview-facet__icon {
	display: inline-flex;
	flex: 0 0 auto;
	color: var(--color-text-muted);
}

.oview-facet__icon svg {
	width: 1.25em;
	height: 1.25em;
	display: block;
}

.oview-facet__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	/* No gap. These are one list, not four separate things, and 5px between
	   32px rows read as more space than the rows themselves. Hover spans the
	   whole row, so they still separate at the moment that matters. */
}

.oview-facet__option {
	display: flex;
	align-items: center;
	gap: var(--space-xs);
	/* WCAG 2.2 SC 2.5.8 wants 24x24. This is the line that turns an inline
	   link into a real target, and into something the gate can even see. */
	min-height: var(--control-h-s);
	padding: 0 var(--space-xs);
	border-radius: var(--radius-s);
	/* --text-s, not the inherited 16px body. An option is a label in a list,
	   not prose, and at 16px eight of them filled the sidebar. */
	font-size: var(--text-xs);
	text-decoration: none;
	color: var(--color-text);
}

/* The name takes the slack, so every count lands on the same right edge. */
.oview-facet__name {
	flex: 1 1 auto;
	min-width: 0;
}

/*
 * The checkbox.
 *
 * Decoration, not a control: the option is a link, and the link's aria-label
 * already says "Filter by X" or "Remove filter X". A real <input> here would
 * need JavaScript to submit and would announce a second, contradictory state.
 * So it is aria-hidden and the semantics stay on the anchor.
 *
 * A rounded square, which needed --radius-xs: --radius-s is 7px, and 7px on an
 * 18px box eats 14 of its 18 and reads as a squircle rather than as a square
 * with a corner on it.
 */
.oview-facet__check {
	flex: 0 0 auto;
	position: relative;
	width: 1.8rem;
	height: 1.8rem;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-s);
	background: var(--color-surface);
}

.oview-facet__option:hover .oview-facet__check {
	border-color: var(--color-border-strong);
}

.oview-facet__option--on .oview-facet__check {
	border-color: var(--color-check);
	background: var(--color-check);
}

/* The tick: two borders of an empty box, rotated. Cheaper than an inline SVG
   repeated once per option, and it scales with the box rather than a viewBox. */
/*
 * The tick: two borders of an empty box, rotated. Cheaper than an inline SVG
 * repeated once per option, and it scales with the box rather than a viewBox.
 *
 * Centred from the middle rather than by hand-picked offsets, which is what
 * the first version did and why it sat low and left. -58% and not -50% on the
 * cross axis because a tick's optical centre is not its bounding box: the long
 * arm carries the weight, so a mathematically centred one reads low.
 */
.oview-facet__option--on .oview-facet__check::after {
	content: "";
	position: absolute;
	left: 50%;
	top: 50%;
	width: 0.4rem;
	height: 0.8rem;
	border: solid var(--color-surface);
	border-width: 0 2px 2px 0;
	transform: translate(-50%, -58%) rotate(45deg);
}

.oview-facet__option:hover,
.oview-facet__option:focus-visible {
	background: var(--color-surface-sunk);
}

/*
 * A selected option gets NO fill. The green tick already says it, and a blue
 * row behind a green check was two signals for one fact, in two hues, one of
 * which then had to be defended on contrast grounds. The row keeps its hover
 * so it still behaves like the others.
 */
.oview-facet__option--on {
	color: var(--color-text);
}

/*
 * The count as a chip rather than as loose grey text. It is a different kind
 * of thing from the name beside it - a measurement, not a label - and a bare
 * number floating at the right edge read as an orphan.
 *
 * tabular-nums so 1,084 and 951 line up on the digit instead of wobbling,
 * which is the entire point of putting numbers in a column.
 */
.oview-facet__count {
	flex: 0 0 auto;
	min-width: 3.6rem;
	padding: 0.2rem var(--space-xs);
	border-radius: var(--radius-s);
	/*
	 * ⚠️ surface-sunk-2, not surface-sunk. The row's hover IS surface-sunk, so
	 * a chip in that colour was invisible at the one moment someone was looking
	 * at the row. It needs to be a step darker than the surface it can land on.
	 *
	 * The text follows: --color-text-muted is 4.31:1 on this and fails AA, so
	 * this is --color-text-body at 5.66:1. Darkening a background moves what may
	 * be written on it.
	 */
	background: var(--color-surface-sunk-2);
	color: var(--color-text-body);
	font-size: var(--text-xs);
	/* 500, matching a card's year. Same kind of thing, same weight. */
	font-weight: 500;
	font-variant-numeric: tabular-nums;
	text-align: center;
}

.oview-facet__option:hover .oview-facet__count,
.oview-facet__option:focus-visible .oview-facet__count {
	color: var(--color-text);
}

/* --- active filter chips ------------------------------------------------ */

.oview-chips__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-xs);
}

.oview-chips__intro {
	/* Same class as the result count, so the two lines of muted supporting
	   text on this page are one thing rather than two near-misses. */
	white-space: nowrap;
}

/*
 * .oview-btn--ghost --s carries the box and the target size; the underline is
 * the part that says this one is a link and not a mode.
 *
 * The padding is the CHIP's, not the small control's. It sits in a row of
 * chips, and --s gives it 12px against their 16px: identical heights, four
 * pixels of difference on each side, and the hover well reads as tighter than
 * everything beside it. Matching neighbours beats matching size class here.
 */
/*
 * The one ghost button with no hover fill.
 *
 * It sits in a row of chips whose padding it can match but whose HEIGHT and
 * radius it cannot, so its hover well always read as a slightly wrong chip
 * however the padding was tuned. Colour says the same thing with nothing to
 * align: red, because this is the control that throws work away.
 *
 * --color-error is 5.90:1 on the surface, so it is a legible text colour and
 * not only a warning one.
 */
.oview-chips__clear {
	text-decoration: underline;
	color: var(--color-text-muted);
}

.oview-chips__clear:hover,
.oview-chips__clear:focus-visible {
	background: transparent;
	color: var(--color-error);
}

/*
 * A chip is a label, not a button, so it takes the control system's small size
 * and its radius rather than being a pill. As a full-radius pill at --space-s
 * it was both taller and much wider than the 12px inside it, and next to a
 * 32px input it read as a different design.
 *
 * It cannot reuse the `pill` global class: Bricks scopes a global class by
 * element type, so `.pill` emits as `.pill.brxe-block` and matches nothing
 * inside a custom element (rules/design.md). Same tokens instead.
 */
.oview-chip {
	display: inline-flex;
	align-items: center;
	gap: var(--space-xs);
	min-height: var(--control-h-s);
	/* The full control padding, not the small one. These are a row of standalone
	   labels rather than something nested, and at 12px they looked pinched. */
	padding-inline: var(--control-px);
	border: 1px solid transparent;
	border-radius: var(--radius-s);
	/* Grey, not accent-soft. A row of blue chips read as five active buttons
	   competing with the one real button on the row above them; these are
	   labels that can be dismissed, and the reference row is grey. */
	background: var(--color-surface-sunk);
	font-size: var(--text-xs);
	line-height: 1.2;
	color: var(--color-text);
	text-decoration: none;
}

.oview-chip:hover,
.oview-chip:focus-visible {
	border-color: var(--color-border);
}

/*
 * There is a token for exactly this: text sitting on the soft accent fill.
 * --color-accent is 3.80:1 on --color-accent-soft and fails AA;
 * --color-on-accent-soft is the same hue darkened, at 5.52:1.
 * The muted grey is worse again at 2.08:1, which is why this is not that.
 */
/* Only rendered when the element is told to. The colon carries the "which
   facet" relationship so the gap between the two can stay small. */
.oview-chip__facet {
	color: var(--color-text-muted);
}

.oview-chip__facet::after {
	content: ":";
}

/*
 * The x sits in its own round well so it reads as the thing that removes the
 * chip, rather than as punctuation at the end of the label. It is not a
 * separate target: the whole chip is the link, and two nested targets 4px
 * apart is worse for a thumb than one 32px one.
 */
/*
 * A rounded square, not a circle. Everything else with a corner in this build
 * is a rounded rectangle - the buttons, the fields, the chip this sits in, the
 * checkbox - and one circle among them read as borrowed from another design.
 */
.oview-chip__remove {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.8rem;
	height: 1.8rem;
	margin-inline-end: -0.5rem;
	border-radius: var(--radius-full);
	color: var(--color-text-muted);
}

/*
 * Drawn, not typed. The &times; glyph is placed by the font's own metrics and
 * sat high and left inside a perfectly centred box; two lines in a square
 * viewBox are centred by construction.
 */
.oview-chip__remove svg {
	width: 1.1rem;
	height: 1.1rem;
	display: block;
	fill: none;
	stroke: currentColor;
	stroke-width: 2.5;
	stroke-linecap: round;
}

.oview-chip:hover .oview-chip__remove,
.oview-chip:focus-visible .oview-chip__remove {
	background: var(--color-text);
	color: var(--color-surface);
}

/* --- sort as a list of orders ------------------------------------------- */

/*
 * One link per order instead of a dropdown, for a sidebar with the room.
 *
 * Platform defaults only: a usable stack of targets, each meeting the tap floor,
 * with the current one saying so. A design that wants them to look like anything
 * else styles these two classes, which is what the contract asks of every other
 * control here.
 */
.oview-sort__list {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--space-2xs);
}

.oview-sort__option {
	display: flex;
	align-items: center;
	min-height: var(--tap-min);
	padding-inline: var(--space-s);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-s);
	background: var(--color-surface);
	/* An order is a choice being read, not a caption. --text-xs is the label
	   scale and put these a step below the options they sit beside. */
	font-size: var(--text-m);
	color: var(--color-text);
	text-decoration: none;
}

.oview-sort__option:hover,
.oview-sort__option:focus-visible {
	border-color: var(--color-border-strong);
	color: var(--color-text);
}

/*
 * ⚠️ The fill AND the border, or the current one is a millimetre taller than the
 * rest: its border is still there, just invisible against its own background.
 */
.oview-sort__option--on,
.oview-sort__option--on:hover {
	border-color: transparent;
	background: var(--color-accent-ink);
	color: var(--color-on-accent);
}

/* --- range (from / to) -------------------------------------------------- */

.oview-range {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: var(--space-xs);
}

/*
 * The box, the border and the focus ring are .oview-field and .oview-btn in
 * controls.css. What is left here is only how they sit next to each other.
 *
 * Two fields and a button on one row at 375px means each gets very little.
 * Flexing from a small basis keeps them side by side instead of stacking.
 */
.oview-range__field {
	flex: 1 1 6rem;
}

/* --- free-text search --------------------------------------------------- */

/*
 * The element root, so the search takes the slack in whatever row it is placed
 * in - the toolbar beside the view switcher today. Without this it sits at its
 * content width and the placeholder truncates mid-word while the row has
 * 400px spare.
 */
.oview-search {
	flex: 1 1 auto;
	min-width: 0;
}

.oview-search__form {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-xs);
}

/* Grow to fill the row; everything else about the box is .oview-field. */
.oview-search__input {
	flex: 1 1 12rem;
}

/* --- facet: disclosure, search within, show more ------------------------ */

.oview-facet__summary {
	display: flex;
	align-items: center;
	gap: var(--space-xs);
	/* A whole-row target, and the chevron still shows the state. */
	min-height: var(--control-h-s);
	cursor: pointer;
}

/*
 * The native marker is a small triangle on the LEFT, which is the one place
 * the eye is not looking: the title starts there. Removing it needs both of
 * these - `list-style: none` for Firefox, the pseudo-element for WebKit, which
 * ignores list-style on a summary.
 */
.oview-facet__summary {
	list-style: none;
}

.oview-facet__summary::-webkit-details-marker {
	display: none;
}

.oview-facet__summary .oview-facet__label {
	display: inline;
	margin: 0;
}

/*
 * The affordance, top right, where BuddyBoss puts it. `margin-inline-start:
 * auto` rather than justify-content, so the badge stays next to the title
 * instead of being pushed to the far side with the chevron.
 */
.oview-facet__chevron {
	flex: 0 0 auto;
	margin-inline-start: auto;
	width: 1.8rem;
	height: 1.8rem;
	color: var(--color-text-muted);
	transition: transform 150ms ease;
}

.oview-facet__chevron svg {
	width: 100%;
	height: 100%;
	display: block;
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.oview-facet__disclosure[open] .oview-facet__chevron {
	transform: rotate(180deg);
}

.oview-facet__summary:hover .oview-facet__chevron {
	color: var(--color-text);
}

/* How many filters are active in a facet that is currently closed. */
.oview-facet__badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 1.8rem;
	min-height: 1.8rem;
	padding: 0 var(--space-2xs);
	border-radius: var(--radius-full);

	/*
	 * ⚠️ THE INK AS A FILL HERE, because the text on it is white and the
	 * contrast is the same 3.72:1 either way round. A badge is small type on a
	 * small chip, which is the worst case for it.
	 */
	background: var(--color-accent-ink);
	color: var(--color-surface);
	font-size: var(--text-xs);
}

.oview-facet__search {
	margin-block: var(--space-2xs);
}

.oview-facet__empty {
	margin: var(--space-2xs) 0;
	font-size: var(--text-xs);
	color: var(--color-text-muted);
}

/* Shape is .oview-btn--ghost --s. "Show more" and "Show fewer" can both be
   present now that expanding is a step rather than a jump to the end. */
.oview-facet__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-2xs);
	margin-top: var(--space-2xs);
}

/*
 * ⚠️ A TEXT LINK, NOT A BUTTON, AND IT USED TO WEAR `.oview-btn`.
 *
 * It sits at the bottom of a list of options, inside a card that already holds a
 * search field and a column of rows. Boxed, it read as a third control competing
 * with those two; what it actually is is the last line of the list, saying there
 * is more of it.
 *
 * The tap floor stays, because losing the box must not lose the target:
 * `check-mobile.js` holds every interactive thing to 24px and this is one.
 */
.oview-facet__more {
	display: inline-flex;
	align-items: center;
	min-height: var(--tap-min);
	padding: 0;
	border: 0;
	background: none;
	font-size: var(--text-xs);
	font-weight: 600;
	color: var(--color-accent-ink);
	text-decoration: none;
	cursor: pointer;
}

.oview-facet__more:hover,
.oview-facet__more:focus-visible {
	color: var(--color-accent-ink);
	text-decoration: underline;
}

/* --- sort ---------------------------------------------------------------- */

/* In the sidebar it is a stacked card: title, then the control. */
.oview-sort__form {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--space-xs);
}

/*
 * ⚠️ .oview-field sets appearance: none, which takes the browser's arrow away
 * with its styling. A select with no arrow is a text box that will not accept
 * typing, so the arrow has to be drawn back - on the WRAPPER, because a
 * <select> cannot carry a pseudo-element.
 */
.oview-sort__control {
	position: relative;
	display: block;
}

.oview-sort__control::after {
	content: "";
	position: absolute;
	/* Two borders of an empty box, rotated: the same chevron the facets use,
	   and it takes currentColor, which a background-image data URI cannot. */
	inset-inline-end: var(--control-px);
	top: 50%;
	width: 0.7rem;
	height: 0.7rem;
	border: solid var(--color-text-muted);
	border-width: 0 2px 2px 0;
	transform: translateY(-70%) rotate(45deg);
	/* Or the arrow eats the click that should open the menu. */
	pointer-events: none;
}

.oview-sort__select {
	/* Full width, unlike a select in a toolbar row: the card already gives it
	   a width, and a select stopping short of its own card looks unfinished.
	   The end padding is the room the arrow above sits in. */
	width: 100%;
	padding-inline-end: calc(var(--control-px) * 2);
	/*
	 * ⚠️ NO font-size. It had one - `--text-s`, the same value the control
	 * system happened to be using - and it was the "two definitions that agree
	 * today" that controls.css opens by warning about. The day the control type
	 * moved to --text-m, every control on the site moved and this one stayed at
	 * 12px: the gate failed on the one field the change had been made FOR.
	 */
	cursor: pointer;
}

/*
 * ⚠️ The chips wrapper is always in the document so the browser has something
 * to replace when a filter changes; when there is nothing to show, this is what
 * makes it invisible rather than a stray gap.
 */
.oview-chips:empty {
	display: none;
}

/*
 * ⚠️ ONE PAGINATION, THE ONE THAT HAS A BUTTON BESIDE IT.
 *
 * This was `.oview-js .brxe-pagination`, which hid EVERY pagination on the site
 * the moment JavaScript ran - and the load more button only existed on the
 * fragrance archive. Brand, accord and note pages lost their numbered links with
 * nothing to replace them, so they were stranded at page one. Found by Dennis on
 * `/brands/avon/`.
 *
 * `filters.js` adds this class only where it finds a button in the same parent,
 * so the fallback disappears exactly where something replaces it and nowhere
 * else.
 */
.oview-pagination--replaced {
	display: none;
}

/*
 * The load more button.
 *
 * ⚠️ ALL OF IT HERE, none of it in element settings: Bricks emits those as
 * `#brxe-{id}

` and no class can beat that, which is why the first version had no
 * hover at all.
 *
 * ⚠️ A native button does NOT get a pointer cursor from the browser - that is a
 * link's default - and its label is still selectable while dragging. Both read
 * as "this is text, not a control".
 */
.oview-load-more {
	/*
	 * ⚠️ ONLY THE CENTRING. Everything else - height, padding, border,
	 * radius, type, colour - came from `.oview-btn` and `--secondary` all along,
	 * and this file was declaring its own copy of each. A control that styles
	 * itself is a control outside the system, which is what `check-controls.js`
	 * failed on.
	 */
	width: fit-content;
	margin: var(--space-l) auto 0;
}

/*
 * ⚠️ THE SAME HOVER THE CARDS USE, WHICH IS BORDER ONLY.
 *
 * `cards.css` states the rule: "Border only, no shadow. Nothing else in this
 * build casts one... If shadows arrive they arrive everywhere at once." A button
 * that also darkens its background is a second hover language on the same page,
 * three inches below thirty things that do it differently.
 */

/* --- A to Z --------------------------------------------------------------- */

/*
 * The letter index, as a control rather than as whatever a drawing drew.
 *
 * ⚠️ THIS IS THE PART THAT DID NOT EXIST, and its absence is the whole reason
 * the A-Z cost more than every other control put together. Its look lived in one
 * mockup's stylesheet, so a second archive could not have one, the selected
 * letter had no class to hang a state on, and a duplicate `All` sat beside the
 * real one because nothing said which was which.
 *
 * Tokens throughout, so a site restyles it by changing a token rather than by
 * overruling these rules - the same bargain the facets and the chips make.
 */
.oview-alpha {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-3xs);
	padding: var(--space-3xs);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-l-2);
	background: var(--color-surface);
}

/*
 * ⚠️ THE TAP FLOOR IS THE POINT, not a nicety. Twenty-seven links in a row is
 * the densest target on the site, and left to its own width a letter is about
 * nine pixels of anchor. `check-mobile.js` holds every interactive thing to 24px
 * and this is where that check earns its place.
 */
.oview-alpha__item {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 1 1 0;
	min-width: var(--tap-min);
	min-height: var(--tap-min);
	border-radius: var(--radius-m-2);
	font-family: var(--font-mono);
	font-size: var(--text-xs);
	color: var(--color-text-body);
	text-decoration: none;
}

/*
 * `All` is a word among letters, so it takes the room a word needs and stops
 * being stretched to a single character's share of the row.
 */
.oview-alpha__item--all {
	flex: 0 0 auto;
	padding-inline: var(--space-l);
	font-family: var(--font-sans);
	font-weight: 700;
}

.oview-alpha__item:hover,
.oview-alpha__item:focus-visible {
	background: var(--color-surface-sunk-2);
	color: var(--color-text);
}

/*
 * ⚠️ A CLASS, WHICH IS WHAT THE LOOP VERSION COULD NOT HAVE. A row cannot add a
 * class to its own element, so the selected letter used to carry an inline style
 * - which landed on the loop's wrapper as well as the link and painted a square
 * behind a round pill.
 */
.oview-alpha__item--on,
.oview-alpha__item--on:hover {
	background: var(--color-text);
	color: var(--color-on-accent);
}

/* ==========================================================================
 * ADOPTED FROM THE BRANDS DRAWING, 2026-08-30.
 *
 * ⚠️ THESE RULES LIVED IN `assets/parts/site-frame-brands.css`, WHICH WAS A
 * DESIGN SYSTEM NOBODY COULD MAINTAIN.
 *
 * `mockup-decompose.php frame` derived that file from one drawing's stylesheet
 * and loaded it on EVERY page. It carried the white card background, the
 * unstriped media and the facet label treatment for the whole site, and three
 * things were wrong with where it lived: nothing in the repo owned it, a hand
 * edit was undone by the next import, and it was only rewritten when somebody
 * re-imported that one drawing. Then a build shrank it by 6,875 bytes and
 * deleted the card design site-wide while reporting nine steps and zero
 * failures.
 *
 * ⚠️ MERGED PROPERTY BY PROPERTY, NOT COPIED. The frame stated some selectors
 * three times: the drawing's rule, then the map's `corrections` restating it
 * where the drawing had our class name wrong. `.oview-facet__name` arrived as
 * mono uppercase, which is what the drawing thought a panel title was, then
 * twice more as sans sentence case, which is what it actually renders as.
 * Copied across, this file would carry a mistake and its own fix side by side.
 *
 * ⚠️ NAMES NO DATASET, which is why it may live in the platform at all. Every
 * value here is a token; what a brand or a fragrance IS appears nowhere.
 *
 * `node scripts/build/adopt-frame.js <mockup>` does the classification for the
 * next drawing. It writes nothing.
 * ========================================================================== */

.oview-facet {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--space-m);
	border: var(--border-hair) solid var(--color-border);
	border-radius: var(--radius-l-2);
	padding: var(--space-m);
	box-sizing: border-box;
}

.oview-facet__head {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-m);
}

.oview-facet__name {
	font-family: var(--font-sans);
	font-size: var(--text-m);
	letter-spacing: normal;
	text-transform: none;
	color: var(--color-text);
	margin: 0;
	font-weight: 500;
	flex: 1;
	min-width: 0;
}

.oview-facet__summary {
	font-size: var(--text-xs);
	font-weight: 700;
	color: var(--color-accent-ink);
	margin: 0;
	display: flex;
	align-items: center;
	gap: var(--space-xs);
}

.oview-facet__chevron {
	width: 1.4rem;
	height: 1.4rem;
	border-right: var(--border-thick) solid var(--color-text-muted);
	border-bottom: var(--border-thick) solid var(--color-text-muted);
	transform: none;
	flex-shrink: 0;
	border: 0;
	color: var(--color-text-muted);
}

.oview-facet__list {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--space-2xs);
	width: 100%;
}

.oview-facet__item {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: var(--space-m);
	min-height: var(--control-h);
	padding: 0 var(--space-m);
	border-radius: var(--radius-m-2);
	box-sizing: border-box;
	width: 100%;
	padding-inline: 0;
}

.oview-facet__item:hover {
	background: var(--color-surface-sunk);
	color: var(--color-text);
}

.oview-facet__check {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: center;
	width: 1.8rem;
	height: 1.8rem;
	border: var(--border-thick) solid var(--color-border-strong);
	border-radius: var(--radius-s);
	background: var(--color-surface);
	color: var(--color-on-accent);
	font-size: var(--text-xs);
	font-weight: 800;
	flex-shrink: 0;
	box-sizing: border-box;
}

.oview-facet__option--on .oview-facet__check {
	border-color: var(--color-purple);
	background: var(--color-purple);
}

.oview-facet__label {
	flex: 1;
	min-width: 0;
	font-size: var(--text-l);
	font-weight: 500;
	margin: 0;
}

.oview-facet__count {
	font-family: var(--font-mono);
	font-size: var(--text-xs);
	color: var(--color-text-muted);
	margin: 0;
	margin-left: auto;
	flex: 0 0 auto;
}

.oview-facet__actions {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-s);
}

.oview-facet__search {
	display: flex;
	flex-direction: row;
	align-items: center;
	width: 100%;
	font-size: var(--text-xs);
	color: var(--color-text-muted);
	background: none;
	border: 0;
	border-radius: var(--radius-m-2);
	min-height: 0;
	padding: 0;
	box-sizing: border-box;
}

.oview-facet__more {
	display: inline-flex;
	flex-direction: row;
	align-items: center;
	font-size: var(--text-xs);
	font-weight: 600;
	color: var(--color-accent-ink);
	min-height: var(--tap-min);
}

.oview-facet--chips {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--space-m);
	border: var(--border-hair) solid var(--color-border);
	border-radius: var(--radius-l-2);
	padding: var(--space-m);
	box-sizing: border-box;
}

.oview-facet--chips .oview-facet__list {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-xs);
}

.oview-facet--chips .oview-facet__item {
	border: var(--border-hair) solid var(--color-border);
	border-radius: var(--radius-full);
	min-height: var(--control-h-s);
	padding: 0 var(--space-m);
	font-size: var(--text-xs);
	font-weight: 600;
}

.oview-facet--chips .oview-facet__label {
	flex: 0 1 auto;
	font-size: var(--text-xs);
	font-weight: 600;
}

.oview-facet__dot {
	width: var(--space-s);
	height: var(--space-s);
	border-radius: var(--radius-full);
	background: var(--color-success);
	flex-shrink: 0;
}

.oview-facet--range {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--space-m);
	border: var(--border-hair) solid var(--color-border);
	border-radius: var(--radius-l-2);
	padding: var(--space-m);
	box-sizing: border-box;
}

.oview-facet--range .oview-facet__list {
	display: flex;
	flex-direction: row;
	align-items: stretch;
	gap: var(--space-xs);
}

/*
 * ⚠️ `.oview-range__field` IS STYLED ONCE, ABOVE, AND WAS STYLED TWICE.
 *
 * A second block here drew the wrapper as a control in its own right: a border,
 * a background, a hover state, and `flex-direction: row`. The markup is a
 * `.oview-control-group`, a label followed by an input, and that class stacks
 * them in a column. Being later in the file, this won: the label sat BESIDE the
 * box, wrapped to two lines, and the year facet read "From / year [1990]".
 *
 * The box, the border and the focus ring belong to `.oview-field` on the input
 * itself, which is what the comment beside the surviving rule already said.
 * Nothing replaced this block because nothing needed to.
 */

.oview-sort__form {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--space-m);
	border: 0;
	border-radius: 0;
	padding: 0;
	box-sizing: border-box;
}

.oview-sort__label {
	font-family: var(--label-font);
	font-size: var(--label-size);
	font-weight: var(--label-weight);
	letter-spacing: var(--label-tracking);
	text-transform: var(--label-case);
	color: var(--label-color);
	margin: 0;
}

.oview-sort__list {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--space-xs);
}

.oview-search__form {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-m);
	flex: 1 1 32rem;
	min-width: 22rem;
}

.oview-search__label {
	font-family: var(--label-font);
	font-size: var(--label-size);
	font-weight: var(--label-weight);
	letter-spacing: var(--label-tracking);
	text-transform: var(--label-case);
	color: var(--label-color);
	margin: 0;
}

.oview-view-switcher {
	display: flex;
	flex-direction: row;
	align-items: center;
	flex-shrink: 0;
	border: 0;
	background: none;
	padding: 0;
	border-radius: 0;
}

.oview-chips {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-m);
}

.oview-chips__list {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-s);
}

.oview-chips__item {
	display: inline-flex;
	flex-direction: row;
	align-items: center;
}

.oview-chip {
	display: inline-flex;
	flex-direction: row;
	align-items: center;
	gap: var(--space-s);
	font-size: var(--text-xs);
	font-weight: 600;
	color: var(--color-on-accent);
	background: var(--color-accent-ink);
	border-radius: var(--radius-full);
	min-height: 2.6rem;
	padding: 0 var(--control-px-s);
	box-sizing: border-box;
	border: 1px solid transparent;
}

/*
 * ⚠️ `--color-accent-ink-hover`, because the chip RESTS at
 * `--color-accent-ink`. It hovered to `--color-accent-hover`, which is the
 * same colour - so the one control whose whole job is "click me to remove this
 * filter" gave no sign it could be clicked.
 */
.oview-chip:hover {
	background: var(--color-accent-ink-hover);
	color: var(--color-on-accent);
}

.oview-chip__value {
	font-size: var(--text-xs);
	font-weight: 600;
}

.oview-chip__remove {
	display: inline-flex;
	flex-direction: row;
	align-items: center;
	justify-content: center;
	min-width: var(--tap-min);
	min-height: var(--tap-min);
	/* Quiet by colour, never opacity (D224): dimming a glyph on a filled chip
	   throws away the contrast the chip's own colours were chosen for. */
	color: var(--color-on-accent);
}

.oview-facet.is-open .oview-facet__list {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--space-2xs);
}

.oview-facet.is-open .oview-facet__actions {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-s);
}

.oview-facet.is-open .oview-facet__chevron {
	transform: rotate(-135deg);
}

.page-numbers {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: center;
	min-width: 3.8rem;
	min-height: 3.8rem;
	padding: 0 var(--space-l);
	font-size: var(--text-l);
	font-weight: 600;
	color: var(--color-text-body);
	border: var(--border-hair) solid var(--color-border);
	border-radius: var(--radius-m-2);
	box-sizing: border-box;
}

.page-numbers:hover {
	background: var(--color-surface-sunk);
	color: var(--color-text);
}

.page-numbers.current {
	font-weight: 700;
	background: var(--color-accent-ink);
	border-color: var(--color-accent-ink);
	color: var(--color-on-accent);
}

.page-numbers.current:hover {
	color: var(--color-on-accent);
}

/*
 * ⚠️ THE TITLE READS AS QUIETER THAN THE THINGS UNDER IT, WHICH IS BACKWARDS.
 *
 * At `--color-text-muted` this is the same grey as a facet's COUNT, so a panel
 * heading and the least important number on the row carried equal weight, and
 * the option labels below - full `--color-text` - outranked the title telling
 * you what you were choosing. Mono, small and uppercase already say "this is a
 * label"; the colour does not have to say it a second time, and saying it twice
 * is what pushed the heading under its own contents.
 *
 * `--color-text-body` rather than `--color-text`: a heading above a list of
 * choices should not compete with the choices either.
 */
.oview-panel .oview-facet__label {
	/* The label (D224), in the body colour for the reason above. */
	font-family: var(--label-font);
	font-size: var(--label-size);
	font-weight: var(--label-weight);
	letter-spacing: var(--label-tracking);
	text-transform: var(--label-case);
	color: var(--color-text-body);
	flex: 1;
	min-width: 0;
	margin: 0;
}

/*
 * And the icon beside it, or the heading darkens and its own glyph stays grey,
 * which reads as the icon being disabled.
 */
.oview-panel .oview-facet__icon {
	color: var(--color-text-body);
}

/*
 * ⚠️ AN OPTION INSIDE A PADDED PANEL DOES NOT PAD AGAIN. This once added
 * --space-l on top of the panel's own padding. On site one's compressed ladder
 * that was 12px and looked like a gap; on an ordinary one it is 21px, and the
 * two together left a facet's name 74px wide, so "Entertainment" truncated and
 * "Social Media" wrapped (D224). The base rule's --space-xs is the ground's
 * breathing room and that is all an option needs.
 */
.oview-facet__option {
	width: 100%;
	flex: 1 1 auto;
}

.oview-facet__disclosure[open] .oview-facet__chevron {
	transform: rotate(180deg);
}

.oview-facet.oview-panel:hover {
	border-color: var(--color-border-strong);
}

.oview-facet.oview-panel:focus-within {
	border-color: var(--color-border-strong);
}

.oview-sort.oview-panel {
	padding: var(--space-m);
	gap: var(--space-m);
	border-radius: var(--radius-l-2);
}

.oview-chip:hover .oview-chip__remove {
	background: var(--color-on-accent);
	color: var(--color-accent-ink);
}

.oview-sort__option {
	min-height: var(--control-h);
	padding-inline: var(--space-m);
	border-radius: var(--radius-m-2);
	font-size: var(--text-m);
	font-weight: 500;
}

.oview-facet__search .oview-field {
	min-height: var(--control-h-s);
	font-size: var(--text-xs);
	padding-inline: var(--control-px-s);
	border-radius: var(--radius-s);
}

/* ==========================================================================
 * The faceted listing's frame: the aside beside the results, the results
 * column, the page head and the empty state. `ov_archive_page()` builds this
 * structure for every site, so its layout is the platform's.
 *
 * ⚠️ IT LIVED IN SITE ONE'S modules.css, so the first listing another site
 * imported (D221) stacked its filters above its results with no gap, no
 * column and an empty state that never hid. A site restyles these in its own
 * stylesheet, which loads after this one.
 * ======================================================================== */

.ov-archive-cols {
	display: grid;
	column-gap: var(--space-xl);
	row-gap: var(--space-l);
}

.ov-archive-cols--left {
	grid-template-columns: minmax(0, var(--width-sidebar)) minmax(0, 1fr);
}

.ov-archive-cols--right {
	grid-template-columns: minmax(0, 1fr) minmax(0, var(--width-sidebar));
}

.ov-archive-cols--right > .ov-archive-aside {
	order: 2;
}

.ov-archive-cols--none {
	grid-template-columns: minmax(0, 1fr);
}

@media (max-width: 767px) {
	.ov-archive-cols,
	.ov-archive-cols--left,
	.ov-archive-cols--right {
		grid-template-columns: minmax(0, 1fr);
	}

	.ov-archive-cols--right > .ov-archive-aside {
		order: 0;
	}
}

.ov-archive-aside {
	display: flex;
	flex-direction: column;
	gap: var(--space-m);
}

.ov-archive-aside--sticky {
	position: sticky;
	top: var(--sticky-top);
	align-self: start;
}

@media (max-width: 767px) {
	.ov-archive-aside--sticky {
		position: static;
	}
}

.ov-archive-main {
	display: flex;
	flex-direction: column;
	gap: var(--space-l);
	min-width: 0;
}

.ov-archive-chips {
	display: flex;
	align-items: center;
}

.ov-page-head {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-2xs);
}

.ov-empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-2xs);
	padding: var(--space-xxl) var(--space-l);
	text-align: center;
	border: var(--border-hair) dashed var(--color-border);
	border-radius: var(--radius-l-2);
	background: var(--color-surface-sunk);
}

.ov-empty-title {
	font-size: var(--text-l);
	font-weight: 700;
	color: var(--color-text);
	margin: 0;
}

/* Results present: no empty state. None: no pager and no Load more. Asked of
 * the whole results column, because a result is any looped row (the site's own
 * card keeps its data-ov-loop) or the platform's card, and an empty sibling such
 * as the active-filter chips says nothing about either. */
.ov-archive-main:has([data-ov-loop], .oview-card) > .ov-empty {
	display: none;
}

.ov-archive-main:not(:has([data-ov-loop], .oview-card)) > .oview-load-more,
.ov-archive-main:not(:has([data-ov-loop], .oview-card)) > .brxe-pagination {
	display: none;
}

/* The filter's stable address (`#filter-genre`), clear of a sticky header when
   a menu link lands on it.
 *
 * ⚠️ A ZERO-HEIGHT FLEX ITEM IS NOT ZERO SPACE.
 *
 * The panel is a flex column with a gap, and this anchor is its first child. At
 * `display: block` it measured 0 tall and still took a gap's worth of room
 * BELOW it, so every facet panel on every site carried an empty band above its
 * first heading, exactly one --space-s high. It read as a broken panel, and
 * nothing was in it. Taking it out of the flow removes the item and the gap
 * with it; `scroll-margin-top` works the same on a positioned element, so the
 * address still lands clear of the header.
 */
.oview-facet {
	position: relative;
}

.oview-facet__anchor {
	position: absolute;
	inset-block-start: 0;
	inline-size: 0;
	block-size: 0;
	scroll-margin-top: calc(var(--oview-header-bottom, 6rem) + var(--space-s));
}
