/**
 * GayRoomies front-end styles.
 *
 * Colours come from the theme via CSS custom properties, with literal
 * fallbacks so the plugin is legible on any theme.
 *
 * A caution learned from the ComunityQ/MaturePride stack: derive the whole
 * palette from one source. Bridging some tokens to a dark theme and leaving
 * others on their light fallbacks produced near-white text on light grey at
 * 1.16:1. Every colour below resolves through --gr-* so a theme can override
 * the set coherently, or none of it.
 */

.gr-listing-form {
	--gr-bg: var(--cq-surface, #ffffff);
	--gr-bg-subtle: var(--cq-surface-2, #f9fafb);
	--gr-text: var(--cq-body-color, #111827);
	--gr-muted: var(--cq-muted, #6b7280);
	--gr-border: var(--cq-border, #e5e7eb);
	--gr-accent: var(--cq-primary, #7c3aed);
	--gr-on-accent: var(--cq-on-primary, #ffffff);
	--gr-radius: var(--cq-container-radius, 8px);
	--gr-btn-radius: var(--cq-button-radius, 6px);

	color: var(--gr-text);
	max-width: 48rem;
	/*
	 * Centred in whatever column it lands in. ComunityQ gives a page a
	 * col-lg-9 of about 1100px; a 768px form pinned to its left edge left a
	 * third of the row empty on one side and read as a rendering fault
	 * rather than a choice.
	 */
	margin-inline: auto;
	counter-reset: gr-form-section;
}

/*
 * A left accent stripe rather than another rounded pill -- see the numbered
 * legend badge below for the same reasoning. Five identical grey boxes in a
 * row read as one long wall; the stripe plus the number is enough to tell
 * them apart without adding more rounded shapes to a page that already has
 * plenty.
 */
.gr-form-section {
	counter-increment: gr-form-section;
	border: 1px solid var(--gr-border);
	border-left: 4px solid var(--gr-accent);
	border-radius: var(--gr-radius);
	padding: 1.25rem 1.5rem 1.5rem;
	margin: 0 0 1.5rem;
	background: var(--gr-bg);
}

.gr-form-section legend {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	font-weight: 700;
	font-size: 1.05rem;
	padding: 0 0.5rem;
	color: var(--gr-text);
}

/*
 * counter(), not a hardcoded 1-5 in the template: Amenities only renders
 * when the site has amenity terms, so a fixed number in markup would leave
 * a gap in the sequence on a fresh install. The counter renumbers itself
 * around whichever sections actually exist.
 */
.gr-form-section legend::before {
	content: counter(gr-form-section);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.65rem;
	height: 1.65rem;
	flex: 0 0 auto;
	border-radius: 50%;
	background: var(--gr-accent);
	color: var(--gr-on-accent);
	font-size: 0.8125rem;
	font-weight: 700;
}

.gr-field {
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
	margin: 0 0 1rem;
}

.gr-field label,
.gr-field__label {
	font-weight: 600;
	font-size: 0.9375rem;
}

/*
 * --gr-radius (the fieldset's own corner radius), not --gr-btn-radius. On
 * this site --gr-btn-radius resolves to a near-pill radius from the theme's
 * button setting, which made every input a stretched-out pill sitting
 * inside a much-less-rounded box. Fields borrow the container's radius
 * instead, so the two nest instead of clashing.
 */
.gr-field input[type="text"],
.gr-field input[type="number"],
.gr-field input[type="date"],
.gr-field select,
.gr-field textarea {
	width: 100%;
	padding: 0.6rem 0.75rem;
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-radius);
	background: var(--gr-bg-subtle);
	color: var(--gr-text);
	font: inherit;
}

.gr-field input:focus-visible,
.gr-field select:focus-visible,
.gr-field textarea:focus-visible {
	outline: 2px solid var(--gr-accent);
	outline-offset: 1px;
}

.gr-required {
	color: #b32d2e;
}

.gr-hint {
	font-size: 0.8125rem;
	color: var(--gr-muted);
}

.gr-hint--block {
	display: block;
	margin-top: 0.5rem;
}

.gr-field-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
	gap: 0 1rem;
}

.gr-checkbox-grid {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 0.6rem;
}

/*
 * Toggle chips, styled with the same --gr-radius as everything else on this
 * page rather than a pill -- amenities were the one place still tempted to
 * go full 999px, and the page already has enough rounded-off shapes.
 */
.gr-checkbox {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.5rem 0.9rem;
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-radius);
	background: var(--gr-bg-subtle);
	font-size: 0.9375rem;
	cursor: pointer;
	transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.gr-checkbox:has( input:checked ) {
	background: var(--gr-accent);
	border-color: var(--gr-accent);
	color: var(--gr-on-accent);
}

.gr-checkbox input[type="checkbox"] {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
}

.gr-checkbox:focus-within {
	outline: 2px solid var(--gr-accent);
	outline-offset: 2px;
}

.gr-photo-strip {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	margin: 0 0 1rem;
}

.gr-photo {
	margin: 0;
	text-align: center;
}

.gr-photo img {
	display: block;
	border-radius: var(--gr-btn-radius);
	border: 1px solid var(--gr-border);
}

.gr-photo.is-primary img {
	border-color: var(--gr-accent);
	border-width: 2px;
}

.gr-photo figcaption {
	font-size: 0.75rem;
	color: var(--gr-muted);
	margin-top: 0.25rem;
}

/*
 * A styled dropzone standing in for the bare "Choose Files / No file
 * chosen" browser control, which was the one visibly unstyled element on an
 * otherwise finished form. The real <input type="file"> sits transparent
 * and full-size on top (gr-photo-upload__input), so a click anywhere in the
 * box, and a native drag-and-drop of files onto it, both still open the
 * normal file picker -- no JS required for the upload itself.
 */
.gr-photo-upload {
	position: relative;
}

.gr-photo-upload__dropzone {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.35rem;
	text-align: center;
	padding: 2rem 1.5rem;
	border: 2px dashed var(--gr-border);
	border-radius: var(--gr-radius);
	background: var(--gr-bg-subtle);
	color: var(--gr-text);
	cursor: pointer;
	transition: border-color 0.15s ease, background 0.15s ease;
}

.gr-photo-upload__icon {
	color: var(--gr-accent);
}

.gr-photo-upload__title {
	font-weight: 600;
}

.gr-photo-upload__filenames {
	font-size: 0.8125rem;
	color: var(--gr-accent);
	font-weight: 600;
}

.gr-photo-upload__filenames:empty {
	display: none;
}

.gr-photo-upload__input {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	opacity: 0;
	cursor: pointer;
}

.gr-photo-upload__input:hover ~ .gr-photo-upload__dropzone,
.gr-photo-upload__input:focus-visible ~ .gr-photo-upload__dropzone {
	border-color: var(--gr-accent);
	background: var(--gr-bg);
}

.gr-photo-upload__input:focus-visible ~ .gr-photo-upload__dropzone {
	outline: 2px solid var(--gr-accent);
	outline-offset: 2px;
}

.gr-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.7rem 1.4rem;
	border: 0;
	border-radius: var(--gr-btn-radius, 6px);
	font-weight: 600;
	cursor: pointer;
	text-decoration: none;
}

.gr-btn--primary {
	background: linear-gradient(135deg, #7c2bc4 0%, #9c3bd3 100%);
	border-color: transparent;
	color: #ffffff;
}

.gr-btn--primary:hover,
.gr-btn--primary:focus-visible {
	background: linear-gradient(135deg, #6920ad 0%, #852bc0 100%);
	color: #ffffff;
}

/*
 * Secondary buttons are genuine outline actions, matching the mockup's
 * “Find a Roommate” control. The parent theme's neutral surface tokens made
 * actions such as “View profile” look disabled, so these stay on-brand.
 */
.gr-btn--secondary {
	background: #ffffff;
	color: #7c2bc4;
	border: 1px solid #7c2bc4;
}

.gr-btn--secondary:hover,
.gr-btn--secondary:focus-visible {
	background: #f7f0ff;
	color: #6920ad;
	border-color: #6920ad;
}

.gr-btn:focus-visible {
	outline: 3px solid rgba(124, 58, 237, 0.38);
	outline-offset: 2px;
}

.gr-form-actions {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.25rem;
}

.gr-notice {
	padding: 1rem 1.25rem;
	border-radius: var(--gr-radius, 8px);
	border-left: 4px solid;
	margin: 0 0 1.5rem;
	background: var(--cq-surface-2, #f9fafb);
	color: var(--cq-body-color, #111827);
}

.gr-notice p:last-child,
.gr-notice ul:last-child {
	margin-bottom: 0;
}

.gr-notice--success {
	border-left-color: #116329;
}

.gr-notice--error {
	border-left-color: #b32d2e;
}

.gr-notice--warn {
	border-left-color: #8a5a00;
}

.gr-notice--info {
	border-left-color: var(--cq-primary, #7c3aed);
}

/* --------------------------------------------------------------------------
   Archive: filters, grid, cards
   -------------------------------------------------------------------------- */

/*
 * Brand orange, defined once.
 *
 * Was #f97316 in two unconnected places -- the listing card and the single
 * page's fact pills -- which meant darkening one for contrast would have
 * silently split the two apart. White on #f97316 measured 2.80:1, under the
 * 4.5:1 WCAG AA needs for body text and under 3:1 for large text; #c2410c
 * takes the same white to 5.18:1 at a shade a viewer would struggle to tell
 * from the original.
 *
 * On :root rather than in a component scope so both users see it: the fact
 * pills live under .gr-single, the cards under .gr-archive, and a token
 * defined in either is invisible to the other.
 */
:root {
	--gr-orange: #c2410c;
	--gr-on-orange: #ffffff;
}

.gr-archive {
	--gr-bg: var(--cq-surface, #ffffff);
	--gr-bg-subtle: var(--cq-surface-2, #f9fafb);
	--gr-text: var(--cq-body-color, #111827);
	--gr-muted: var(--cq-muted, #6b7280);
	--gr-border: var(--cq-border, #e5e7eb);
	--gr-accent: var(--cq-primary, #7c3aed);
	--gr-on-accent: var(--cq-on-primary, #ffffff);
	--gr-radius: var(--cq-container-radius, 8px);
	--gr-btn-radius: var(--cq-button-radius, 6px);

	color: var(--gr-text);
}

/*
 * The filter bar, tinted rather than grey.
 *
 * It used to be three shades of the same non-colour stacked on each other:
 * the panel on --gr-bg-subtle (#f9fafb), the fields on --gr-bg-subtle too --
 * because .gr-field's input rule (0,2,1) outranks .gr-filters' (0,1,1) -- and
 * --gr-border (#e5e7eb) drawing the line between them. Panel and field sat
 * 1.09:1 apart, so the inputs stopped reading as things you could type into.
 * The one field that did look like an input was the location box, and only by
 * accident: it is type="search", which .gr-field's selector list never named,
 * so it fell through to the white .gr-filters rule. Fixing that inconsistency
 * on its own would have made the bar *more* uniformly grey, not less.
 *
 * So the panel takes a wash of the brand primary instead. Every colour still
 * derives from --gr-accent and --gr-bg, per the note at the top of this file:
 * a theme that moves its primary moves the whole filter bar with it, rather
 * than leaving a purple panel stranded on a repainted page.
 *
 * The literals below are the mix computed against this site's palette
 * (#7c3aed on #ffffff) and are what browsers without color-mix() get. The
 * @supports block then re-derives them. Order matters and so does the guard:
 * a custom property accepts color-mix() as a token stream whether or not the
 * browser can resolve it, so an unguarded override would win the cascade and
 * then fail at use, dropping the background entirely.
 *
 * Contrast on the tint: labels 8.48:1, the muted "Popular:" label 10.51:1,
 * field text 16.22:1.
 */
.gr-filters {
	--gr-filter-bg: #f7f3fe;
	--gr-filter-border: #e2d4fb;
	--gr-filter-field-border: #d5c0f9;
	--gr-filter-label: #532da2;
	--gr-filter-muted: #412780;

	background: var(--gr-filter-bg);
	border: 1px solid var(--gr-filter-border);
	border-radius: var(--gr-radius);
	padding: 1rem 1.25rem;
	margin: 0 0 1.5rem;
}

@supports (color: color-mix(in srgb, #000, #fff)) {
	.gr-filters {
		--gr-filter-bg: color-mix(in srgb, var(--gr-accent, #7c3aed) 6%, var(--gr-bg, #ffffff));
		--gr-filter-border: color-mix(in srgb, var(--gr-accent, #7c3aed) 22%, var(--gr-bg, #ffffff));
		--gr-filter-field-border: color-mix(in srgb, var(--gr-accent, #7c3aed) 32%, var(--gr-bg, #ffffff));
		--gr-filter-label: color-mix(in srgb, var(--gr-accent, #7c3aed) 62%, var(--gr-text, #111827));
		--gr-filter-muted: color-mix(in srgb, var(--gr-accent, #7c3aed) 45%, var(--gr-text, #111827));
	}
}

.gr-filters__row {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
	gap: 0 1rem;
	align-items: end;
}

.gr-filters .gr-field {
	margin-bottom: 0.75rem;
}

.gr-filters .gr-field label,
.gr-filters .gr-field__label {
	color: var(--gr-filter-label);
}

/*
 * Both the bare descendant selector and the .gr-field one, so the rule wins
 * wherever the markup puts the input -- the listings bar wraps fields in <p>,
 * the member directory and services archive in <label>. Naming no input types
 * is deliberate: it is what let type="search" drift off on its own before.
 */
.gr-filters input,
.gr-filters select,
.gr-filters .gr-field input,
.gr-filters .gr-field select {
	width: 100%;
	padding: 0.55rem 0.7rem;
	border: 1px solid var(--gr-filter-field-border);
	border-radius: var(--gr-btn-radius);
	background: var(--gr-bg);
	color: var(--gr-text);
	font: inherit;
}

/*
 * The verified-members checkbox is the one control that must not take the
 * field treatment. It was already inheriting width:100% and 0.55rem padding
 * from the rule above, which stretched it into a full-width bar with a tick
 * lost somewhere inside -- longstanding, just easier to see now that the
 * fields have a visible edge.
 */
.gr-filters .gr-field--check input[type="checkbox"] {
	width: auto;
	padding: 0;
	accent-color: var(--gr-accent);
}

.gr-filters input::placeholder {
	color: var(--gr-muted);
	opacity: 1;
}

.gr-budget-pair {
	display: flex;
	align-items: center;
	gap: 0.4rem;
}

.gr-filters__popular {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin-top: 0.25rem;
}

.gr-filters__popular-label {
	font-size: 0.875rem;
	color: var(--gr-filter-muted);
}

/*
 * Filter chips only. .gr-chip is also the amenity pill on the single listing
 * and the role badge on member cards and profiles, none of which sit on the
 * tint -- so these overrides stay scoped to .gr-filters.
 */
.gr-filters .gr-chip {
	border-color: var(--gr-filter-field-border);
	color: var(--gr-filter-label);
}

.gr-filters .gr-chip:hover,
.gr-filters .gr-chip:focus-visible {
	border-color: var(--gr-accent);
	color: var(--gr-accent);
}

/*
 * The selected city is filled, not just outlined. On the tint an outline-only
 * active state was hard to pick out of the row at a glance.
 */
.gr-filters .gr-chip.is-active {
	background: var(--gr-accent);
	border-color: var(--gr-accent);
	color: var(--gr-on-accent);
}

/*
 * Search, in the brand orange rather than the site purple.
 *
 * --gr-orange is the same token the listing cards and the single page's fact
 * pills read, so the bar's primary action now points at the same colour the
 * results below it are painted in, and it stops sharing a hue with the panel
 * it sits on.
 *
 * The 2px border with padding stepped back by 2px keeps the outer box
 * identical to every other .gr-btn, so nothing reflows against the Clear
 * button beside it and nothing moves between rest and hover.
 *
 * Measured: orange label on the white fill 5.18:1, the border against the
 * tint 4.74:1, and white on orange 5.18:1 on hover. The white fill itself is
 * only 1.09:1 against the tint -- that is fine here, and it is the same
 * reading that made the Clear button below go transparent. The difference is
 * what carries the shape: Clear had a purple border on a purple-tinted panel,
 * so the fill was the only thing distinguishing it and it was doing nothing.
 * Here the orange border and label carry it at 4.74:1 and the fill is a lift,
 * not the load-bearing part.
 */
.gr-filters .gr-btn--primary {
	background: #ffffff;
	color: var(--gr-orange, #c2410c);
	border: 2px solid var(--gr-orange, #c2410c);
	padding: calc(0.7rem - 2px) calc(1.4rem - 2px);
}

/*
 * Hover inverts to a filled orange pill ringed in white. On the tinted panel
 * the ring is 1.09:1 and so reads as a hairline of breathing room around the
 * orange rather than as a visible white line -- which is the intent: it holds
 * the fill off the panel without drawing a second edge.
 */
.gr-filters .gr-btn--primary:hover,
.gr-filters .gr-btn--primary:focus-visible {
	background: var(--gr-orange, #c2410c);
	color: #ffffff;
	border-color: #ffffff;
}

/*
 * The shared .gr-btn focus ring is a purple halo, which on an orange button
 * reads as a stray colour. Same ring, orange.
 */
.gr-filters .gr-btn--primary:focus-visible {
	outline: 3px solid rgba(194, 65, 12, 0.45);
	outline-offset: 2px;
}

/*
 * The Clear button is a white-filled outline button everywhere else on the
 * site. On the tint that white fill measures 1.09:1 against the panel -- the
 * same figure as the grey-on-grey the tint was brought in to fix -- so it
 * read as a floating border with nothing behind it. Transparent instead, so
 * it is honestly an outline button sitting on the panel, and the hover state
 * deepens the tint rather than trying to out-white a near-white ground.
 *
 * Scoped to .gr-filters: on white surfaces the fill is doing real work and
 * .gr-btn--secondary stays as it is.
 */
.gr-filters .gr-btn--secondary {
	background: transparent;
}

.gr-filters .gr-btn--secondary:hover,
.gr-filters .gr-btn--secondary:focus-visible {
	background: var(--gr-filter-field-border);
}

.gr-chip {
	display: inline-block;
	padding: 0.3rem 0.8rem;
	border: 1px solid var(--gr-border);
	border-radius: 999px;
	background: var(--gr-bg);
	color: var(--gr-text);
	font-size: 0.875rem;
	text-decoration: none;
}

.gr-chip.is-active,
.gr-chip:hover {
	border-color: var(--gr-accent);
	color: var(--gr-accent);
}

.gr-archive__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	margin: 0 0 1rem;
}

.gr-archive__count {
	margin: 0;
	color: var(--gr-muted);
}

.gr-archive__sort {
	margin: 0;
}

.gr-archive__sort select {
	padding: 0.45rem 0.6rem;
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-btn-radius);
	background: var(--gr-bg);
	color: var(--gr-text);
	font: inherit;
}

/* --- Listings map -------------------------------------------------------- */

.gr-map-wrap {
	margin: 0 0 1.5rem;
}

.gr-map {
	height: 22rem;
	border-radius: var(--gr-radius);
	border: 1px solid var(--gr-border);
	overflow: hidden;
	/* Leaflet positions its panes absolutely inside this box; without an
	   explicit z-index the tiles can sit above a sticky site header. */
	z-index: 0;
}

@media (max-width: 767.98px) {
	.gr-map {
		height: 15rem;
	}
}

/*
 * The precision caveat is part of the map, not a footnote to it. Styled to be
 * read rather than skipped, because a visitor who assumes a pin is an address
 * has been actively misled.
 */
.gr-map__note {
	margin: 0.5rem 0 0;
	font-size: 0.8125rem;
	color: var(--gr-muted);
}

.gr-map__popup {
	display: grid;
	gap: 0.15rem;
	min-width: 11rem;
}

.gr-map__popup-img {
	width: 100%;
	height: 6rem;
	object-fit: cover;
	border-radius: var(--gr-btn-radius);
	margin-bottom: 0.25rem;
}

.gr-map__popup-title {
	font-weight: 700;
	font-size: 0.95rem;
	line-height: 1.3;
	color: var(--gr-text);
	text-decoration: none;
}

.gr-map__popup-title:hover {
	text-decoration: underline;
}

.gr-map__popup-price {
	font-weight: 700;
	color: var(--gr-accent);
}

.gr-map__popup-place,
.gr-map__popup-note {
	font-size: 0.8125rem;
	color: var(--gr-muted);
}

.gr-map__popup-note {
	font-style: italic;
}

.gr-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
	gap: 1.25rem;
}

.gr-card {
	background: var(--gr-bg);
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-radius);
	overflow: hidden;
	display: flex;
	flex-direction: column;
}

.gr-card__media {
	position: relative;
	aspect-ratio: 4 / 3;
	background: var(--gr-bg-subtle);
}

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

.gr-card__placeholder {
	display: block;
	width: 100%;
	height: 100%;
	background: var(--gr-bg-subtle);
}

.gr-card__badge {
	position: absolute;
	top: 0.6rem;
	left: 0.6rem;
	background: var(--gr-bg);
	color: var(--gr-text);
	border-radius: 999px;
	padding: 0.25rem 0.7rem;
	font-size: 0.75rem;
	font-weight: 600;
}

.gr-favorite {
	position: absolute;
	top: 0.6rem;
	right: 0.6rem;
	width: 2.1rem;
	height: 2.1rem;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 0;
	border-radius: 999px;
	background: var(--gr-bg);
	color: var(--gr-muted);
	cursor: pointer;
	padding: 0;
}

.gr-favorite svg {
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linejoin: round;
}

.gr-favorite.is-favorited {
	color: #d6336c;
}

.gr-favorite.is-favorited svg {
	fill: currentColor;
}

/*
 * The heart is 2.1rem (34px) square, which clears the WCAG 2.2 AA minimum of
 * 24px but is small for the one control on a listing card that a phone
 * visitor is meant to hit -- and it sits in a corner, next to the card's own
 * link, where a near miss navigates away instead. Enlarged to 44px on coarse
 * pointers only: the constraint is the thumb, not the viewport, so a narrow
 * desktop window keeps the compact heart.
 */
@media (pointer: coarse) {
	.gr-favorite {
		width: 2.75rem;
		height: 2.75rem;
	}
}

/* Visible keyboard focus: the heart sits on a photo, where a default outline
   frequently disappears against the image. */
.gr-favorite:focus-visible {
	outline: 2px solid var(--gr-accent);
	outline-offset: 2px;
}

.gr-card__body {
	padding: 0.85rem 1rem 1rem;
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
	flex: 1;
}

.gr-card__title {
	margin: 0;
	font-size: 1rem;
	line-height: 1.35;
}

.gr-card__title a {
	color: inherit;
	text-decoration: none;
}

.gr-card__title a:hover {
	text-decoration: underline;
}

.gr-card__location {
	margin: 0;
	font-size: 0.875rem;
	color: var(--gr-muted);
}

.gr-card__price {
	margin: 0.2rem 0 0;
	color: var(--gr-accent);
	font-size: 1.0625rem;
}

.gr-card__period {
	font-size: 0.8125rem;
	color: var(--gr-muted);
}

/*
 * Availability reads as a status line rather than another fact: it is the one
 * thing on the card that can rule a listing out at a glance, so it sits above
 * the beds/baths row instead of inside it.
 */
.gr-card:not(.gr-member-card) .gr-card__avail {
	margin: 0.15rem 0 0;
	font-size: 0.8125rem;
	font-weight: 600;
	color: var(--gr-card-fg);
}

.gr-card__amenities {
	list-style: none;
	margin: 0.4rem 0 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 0.3rem;
}

.gr-card:not(.gr-member-card) .gr-card__amenities li {
	padding: 0.1rem 0.5rem;
	border-radius: 999px;
	font-size: 0.75rem;
	font-weight: 600;
	/* A translucent white plate rather than another colour: the card already
	   carries one strong hue and a second would compete with the price. */
	background: rgba(255, 255, 255, 0.18);
	border: 1px solid rgba(255, 255, 255, 0.35);
	color: var(--gr-card-fg);
}

.gr-empty .gr-cta {
	margin-top: 0.35rem;
}

.gr-card__facts {
	list-style: none;
	margin: 0.4rem 0 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	font-size: 0.8125rem;
	color: var(--gr-muted);
	border-top: 1px solid var(--gr-border);
	padding-top: 0.6rem;
	margin-top: auto;
}

/* --- Listing card colours -------------------------------------------------
 *
 * A listing card is an orange tile with white type. Both halves of that pair
 * are pinned here rather than read from --gr-bg / --gr-text, because white
 * text over a token stays legible only for as long as that token happens to
 * resolve dark -- and --gr-bg bridges to --cq-surface, a ComunityQ Customizer
 * value the site owner can change from under it. Setting the background and
 * the foreground together in one place makes white-on-white unreachable.
 *
 * The orange comes from --gr-orange, shared with the single listing page's
 * fact pills, so a card and the listing it opens cannot drift apart.
 *
 * Scoped off .gr-member-card: the profile directory reuses this markup
 * (class="gr-card gr-member-card") and is not part of this treatment.
 */
.gr-card:not(.gr-member-card) {
	/*
	 * Contrast, measured: white on --gr-orange (#c2410c) is 5.18:1, clearing
	 * the 4.5:1 WCAG AA needs for body text. The previous #f97316 measured
	 * 2.80:1 and failed both that and the 3:1 large-text floor.
	 */
	--gr-card-bg: var(--gr-orange);
	--gr-card-fg: #ffffff;

	/*
	 * Secondary text is white at reduced opacity, never grey. --gr-muted is
	 * chosen to sit on a light surface and lands near 2:1 against this
	 * orange; holding everything to a white-derived value keeps the location,
	 * period and facts subordinate to the title without reintroducing the
	 * grey-on-orange this rule exists to remove. Held at 0.92 rather than
	 * anything lower: on a background this light every point of alpha comes
	 * straight off an already-marginal contrast figure (0.87 measured
	 * 2.46:1 against the card, below the plain white beside it).
	 */
	--gr-card-fg-soft: rgba(255, 255, 255, 0.92);

	background: var(--gr-card-bg);
	border-color: var(--gr-card-bg);
	color: var(--gr-card-fg);
}

/*
 * The title link is listed with :hover and :visited because a parent theme
 * setting link colours globally would otherwise repaint it on hover only --
 * a card whose heading changes colour when the mouse crosses it.
 */
.gr-card:not(.gr-member-card) .gr-card__title,
.gr-card:not(.gr-member-card) .gr-card__title a,
.gr-card:not(.gr-member-card) .gr-card__title a:hover,
.gr-card:not(.gr-member-card) .gr-card__title a:focus,
.gr-card:not(.gr-member-card) .gr-card__title a:visited,
.gr-card:not(.gr-member-card) .gr-card__price,
.gr-card:not(.gr-member-card) .gr-card__price strong {
	color: var(--gr-card-fg);
}

.gr-card:not(.gr-member-card) .gr-card__location,
.gr-card:not(.gr-member-card) .gr-card__period,
.gr-card:not(.gr-member-card) .gr-card__facts {
	color: var(--gr-card-fg-soft);
}

/* The divider above the facts row was --gr-border, a pale grey that has
   nothing left to separate once the card behind it is orange. */
.gr-card:not(.gr-member-card) .gr-card__facts {
	border-top-color: rgba(255, 255, 255, 0.4);
}

.gr-pagination {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	justify-content: center;
	margin: 2rem 0 0;
}

.gr-pagination .page-numbers {
	padding: 0.45rem 0.8rem;
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-btn-radius);
	text-decoration: none;
	color: var(--gr-text);
}

.gr-pagination .page-numbers.current {
	background: var(--gr-accent);
	color: var(--gr-on-accent);
	border-color: var(--gr-accent);
}

.gr-empty {
	text-align: center;
	padding: 3rem 1rem;
	border: 1px dashed var(--gr-border);
	border-radius: var(--gr-radius);
	color: var(--gr-muted);
}

.gr-empty h2 {
	margin-top: 0;
	color: var(--gr-text);
}

/* ---------------------------------------------------------------------------
 * Profiles (Phase 4)
 *
 * Deliberately reuses .gr-card, .gr-grid and .gr-chip rather than introducing
 * a parallel set of member-only primitives -- a member card and a listing card
 * sit next to each other on a profile page, and two sets of tokens is how they
 * drift apart.
 *
 * Every rule that sets a background on an interactive element also sets color.
 * A <button> or <a class="gr-btn"> given only a background inherits the UA
 * default for its label, which resolves to black and disappears on a dark
 * palette. This bit the CommunityQ stack repeatedly; not repeating it here.
 * ------------------------------------------------------------------------ */

.gr-profile {
	/*
	 * Self-contained --gr-* block, same as .gr-archive, .gr-listing-form and
	 * .gr-single above -- and the one this file's own header comment warned
	 * about without actually being applied here. Without it, every var(--gr-*)
	 * below (and in the listing cards nested inside "Listings from X") had no
	 * definition to resolve against: background properties computed to
	 * transparent, non-inherited colours fell through to whatever the theme's
	 * ambient text colour happened to be, and a listing card sitting on a
	 * transparent background over other content is exactly the kind of
	 * "text you can't read" bug this class's own comment predicted.
	 */
	--gr-bg: var(--cq-surface, #ffffff);
	--gr-bg-subtle: var(--cq-surface-2, #f9fafb);
	--gr-text: var(--cq-body-color, #111827);
	--gr-muted: var(--cq-muted, #6b7280);
	--gr-border: var(--cq-border, #e5e7eb);
	--gr-accent: var(--cq-primary, #7c3aed);
	--gr-on-accent: var(--cq-on-primary, #ffffff);
	--gr-radius: var(--cq-container-radius, 8px);
	--gr-btn-radius: var(--cq-button-radius, 6px);

	color: var(--gr-text);
	max-width: 68rem;
	margin: 0 auto;
}

/*
 * Cover banner.
 *
 * A fixed aspect ratio rather than a fixed height: members upload whatever
 * their phone produced, and a height alone would letterbox a tall image into a
 * strip of somebody's chin. The ratio narrows on small screens because 4:1 of
 * a 375px viewport is under 95px of banner once padding is taken off, which is
 * not enough to read as an image at all.
 */
/*
 * Profile completion nudge. Owner-only, so it sits above the header rather
 * than inside it -- it is a message about the page, not part of the profile,
 * and it disappears entirely once there is nothing left to prompt for.
 */
.gr-profile-nudge {
	border: 1px solid var(--gr-border);
	border-left: 4px solid var(--gr-accent);
	border-radius: var(--gr-radius);
	background: var(--gr-bg-subtle);
	padding: 1rem 1.25rem 1.1rem;
	margin: 0 0 1.5rem;
}

.gr-profile-nudge__head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.5rem;
}

.gr-profile-nudge__title {
	margin: 0;
	font-size: 1.05rem;
	color: var(--gr-text);
}

.gr-profile-nudge__meta {
	margin: 0;
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--gr-accent);
}

.gr-profile-nudge__bar {
	height: 0.4rem;
	border-radius: 999px;
	background: var(--gr-border);
	overflow: hidden;
	margin: 0.6rem 0 0.8rem;
}

.gr-profile-nudge__bar span {
	display: block;
	height: 100%;
	background: var(--gr-accent);
	border-radius: inherit;
}

.gr-profile-nudge__lead {
	margin: 0 0 0.5rem;
	font-size: 0.9375rem;
}

.gr-profile-nudge__list {
	margin: 0 0 1rem;
	padding-left: 1.1rem;
	display: grid;
	gap: 0.25rem;
	font-size: 0.9375rem;
}

.gr-profile-nudge__action {
	margin: 0;
}

.gr-profile__cover {
	aspect-ratio: 4 / 1;
	overflow: hidden;
	border-radius: var(--gr-radius) var(--gr-radius) 0 0;
	background: var(--gr-bg-subtle);

	/*
	 * No bottom margin: the header sits directly beneath and its own top
	 * corners are squared off, so the two read as one card. They used to be a
	 * floating banner with a separate bordered box under it, which looked like
	 * two unrelated components that happened to be adjacent.
	 */
	margin-bottom: 0;
}

.gr-profile__cover img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	display: block;
}

@media (max-width: 575.98px) {
	.gr-profile__cover {
		aspect-ratio: 5 / 2;
		margin-bottom: 1rem;
	}
}

/* --- Verification ------------------------------------------------------- */

/*
 * Verification is the one page on the site that asks a member to hand over a
 * photo of their own face. It has to look like somebody built it on purpose,
 * because a page asking for that in unstyled default markup reads as a phish.
 * Hence the state mark, the stepped list and the explicit note about what
 * happens to the file -- reassurance is the feature here, not decoration.
 */

.gr-verify {
	--gr-verify-tone: var(--gr-accent, #7c3aed);

	max-width: 42rem;
	padding: 1.75rem;
	border: 1px solid var(--gr-border, #e5e7eb);
	border-radius: var(--gr-radius, 8px);
	background: var(--gr-bg, #ffffff);
}

/* The tone carries the state, so the mark, the rule and the code all shift
   together instead of needing a colour rule each. */
.gr-verify--done {
	--gr-verify-tone: #116329;
}

.gr-verify--waiting {
	--gr-verify-tone: #8a5a00;
}

.gr-verify__head {
	display: flex;
	align-items: flex-start;
	gap: 1rem;
	margin: 0 0 1.5rem;
}

.gr-verify__mark {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 3rem;
	height: 3rem;
	border-radius: 50%;
	background: #f3f0fb;
	background: color-mix(in srgb, var(--gr-verify-tone) 12%, transparent);
	color: var(--gr-verify-tone);
}

.gr-verify__mark svg {
	width: 1.6rem;
	height: 1.6rem;
}

.gr-verify__headings {
	min-width: 0;
}

.gr-verify__title {
	margin: 0 0 0.35rem;
	font-size: 1.4rem;
	line-height: 1.25;
	color: var(--gr-text, #111827);
}

.gr-verify__lead {
	margin: 0;
	color: var(--gr-muted, #6b7280);
	line-height: 1.6;
}

/*
 * A counter rather than the browser's numbers: the marker needs to be a
 * filled circle sitting on the connecting rule, which list-item markers
 * cannot be positioned to do.
 */
.gr-verify__steps {
	counter-reset: gr-verify-step;
	list-style: none;
	margin: 0 0 1.75rem;
	padding: 0;
}

.gr-verify__step {
	counter-increment: gr-verify-step;
	position: relative;
	padding: 0 0 1.25rem 3rem;
}

.gr-verify__step::before {
	content: counter(gr-verify-step);
	position: absolute;
	left: 0;
	top: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 1.9rem;
	height: 1.9rem;
	border-radius: 50%;
	background: var(--gr-verify-tone);
	color: #ffffff;
	font-size: 0.85rem;
	font-weight: 700;
	line-height: 1;
}

/* The rule joins one step to the next, so it stops at the last one. */
.gr-verify__step::after {
	content: "";
	position: absolute;
	left: 0.95rem;
	top: 2.15rem;
	bottom: 0.25rem;
	width: 2px;
	background: var(--gr-border, #e5e7eb);
}

.gr-verify__step:last-child {
	padding-bottom: 0;
}

.gr-verify__step:last-child::after {
	display: none;
}

.gr-verify__step-text {
	margin: 0.2rem 0 0;
	line-height: 1.6;
	color: var(--gr-text, #111827);
}

.gr-verify__code-wrap {
	margin: 0.75rem 0 0;
}

/*
 * The code has to be readable well enough to copy onto paper by hand, which
 * is a different job from ordinary inline code and wants the size to match.
 * user-select: all so one click takes the whole string -- the hyphen makes a
 * double-click select only half of it.
 */
.gr-verify__code {
	display: inline-block;
	padding: 0.6rem 1.1rem;
	border: 2px dashed var(--gr-verify-tone);
	border-radius: var(--gr-radius, 8px);
	background: #f3f0fb;
	background: color-mix(in srgb, var(--gr-verify-tone) 8%, transparent);
	color: var(--gr-verify-tone);
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: 1.6rem;
	font-weight: 700;
	letter-spacing: 0.12em;
	line-height: 1.1;
	user-select: all;
	-webkit-user-select: all;
}

.gr-verify__form {
	margin: 0;
}

/*
 * A drop-zone look for a plain file input. No JavaScript behind it -- the
 * dashed frame is there so the control reads as "put something here" at a
 * glance, which the browser's default button on its own does not.
 */
.gr-verify__upload {
	display: block;
	padding: 1.25rem;
	border: 2px dashed var(--gr-border, #e5e7eb);
	border-radius: var(--gr-radius, 8px);
	background: var(--gr-bg-subtle, #f9fafb);
	cursor: pointer;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}

.gr-verify__upload:hover,
.gr-verify__upload:focus-within {
	border-color: var(--gr-verify-tone);
	background: #ffffff;
}

.gr-verify__upload input[type="file"] {
	display: block;
	width: 100%;
	margin: 0.5rem 0 0.4rem;
	font: inherit;
	color: var(--gr-text, #111827);
}

.gr-verify__upload input[type="file"]::file-selector-button {
	margin-right: 0.75rem;
	padding: 0.5rem 1rem;
	border: 1px solid var(--gr-verify-tone);
	border-radius: var(--gr-btn-radius, 6px);
	background: #ffffff;
	color: var(--gr-verify-tone);
	font: inherit;
	font-weight: 600;
	cursor: pointer;
}

.gr-verify__submit {
	margin: 1.25rem 0 0;
}

/* Touch targets: WCAG 2.2 wants 24px, and a phone wants rather more. */
.gr-verify__submit .gr-btn {
	min-height: 2.75rem;
}

.gr-verify__privacy {
	display: flex;
	align-items: flex-start;
	gap: 0.85rem;
	margin: 1.75rem 0 0;
	padding: 1rem 1.15rem;
	border-radius: var(--gr-radius, 8px);
	background: var(--gr-bg-subtle, #f9fafb);
	color: var(--gr-muted, #6b7280);
	font-size: 0.875rem;
	line-height: 1.6;
}

.gr-verify__privacy p {
	margin: 0;
}

.gr-verify__privacy-mark {
	flex: 0 0 auto;
	color: var(--gr-text, #111827);
}

.gr-verify__privacy-mark svg {
	width: 1.15rem;
	height: 1.15rem;
	display: block;
	margin-top: 0.15rem;
}

.gr-verify__privacy-title {
	font-weight: 700;
	color: var(--gr-text, #111827);
	margin-bottom: 0.2rem !important;
}

@media (max-width: 575.98px) {
	.gr-verify {
		padding: 1.25rem;
	}

	.gr-verify__head {
		gap: 0.75rem;
	}

	.gr-verify__mark {
		width: 2.5rem;
		height: 2.5rem;
	}

	.gr-verify__mark svg {
		width: 1.3rem;
		height: 1.3rem;
	}

	.gr-verify__title {
		font-size: 1.2rem;
	}

	.gr-verify__code {
		font-size: 1.3rem;
		letter-spacing: 0.08em;
	}
}


.gr-field--check {
	flex-direction: row;
	align-items: center;
	gap: 0.45rem;
}

/* --- Compatibility panel on a profile ----------------------------------- */

.gr-match-panel {
	border: 1px solid var(--gr-border);
	border-left-width: 4px;
	border-radius: var(--gr-radius);
	background: var(--gr-bg-subtle);
	padding: 1rem 1.25rem;
}

.gr-match-panel--high { border-left-color: #0ca30c; }
.gr-match-panel--good { border-left-color: var(--gr-accent); }
.gr-match-panel--low,
.gr-match-panel--blocked { border-left-color: var(--gr-border); }

.gr-match-panel__score {
	display: flex;
	align-items: baseline;
	gap: 0.4rem;
	margin: 0;
}

.gr-match-panel__pct {
	font-size: 1.75rem;
	font-weight: 800;
	line-height: 1;
	color: var(--gr-text);
}

.gr-match-panel__label {
	font-weight: 600;
	color: var(--gr-muted);
}

/*
 * The reasons are the point of this panel, so they are body text rather than
 * fine print -- a percentage nobody can interrogate is a percentage they stop
 * believing.
 */
.gr-match-panel__reasons {
	list-style: none;
	margin: 0.6rem 0 0;
	padding: 0;
	display: grid;
	gap: 0.25rem;
	font-size: 0.9375rem;
	color: var(--gr-text);
}

.gr-match-panel__reasons li::before {
	content: "\2022";
	color: var(--gr-accent);
	font-weight: 700;
	margin-right: 0.5rem;
}

.gr-match-panel__why {
	margin: 0;
	color: var(--gr-muted);
}

/* --- Compatibility badge ------------------------------------------------
 *
 * Band colour plus the number, never colour alone: the percentage is the
 * information and the tint only reinforces it, so nothing is lost to a
 * colourblind reader or a monochrome print.
 */
.gr-match {
	display: inline-flex;
	align-items: baseline;
	gap: 0.3rem;
	margin: 0 0 0.4rem;
	padding: 0.2rem 0.6rem;
	border-radius: 999px;
	font-size: 0.8125rem;
	font-weight: 600;
	border: 1px solid transparent;
}

.gr-match__pct {
	font-size: 0.95rem;
	font-weight: 700;
}

.gr-match--high {
	background: #e7f6e7;
	border-color: #bfe5bf;
	color: #14620f;
}

.gr-match--good {
	background: #eef2ff;
	border-color: #cdd7fb;
	color: #2b3fa0;
}

.gr-match--low {
	background: var(--gr-bg-subtle);
	border-color: var(--gr-border);
	color: var(--gr-muted);
}

/* Not a match is a statement about the pairing, not a low score, so it reads
   as a sentence rather than a number. */
.gr-match--blocked {
	flex-direction: column;
	align-items: flex-start;
	gap: 0.1rem;
	border-radius: var(--gr-radius);
	background: var(--gr-bg-subtle);
	border-color: var(--gr-border);
	color: var(--gr-muted);
	font-weight: 500;
	text-align: left;
}

.gr-match--blocked .gr-match__label {
	font-weight: 700;
	color: var(--gr-text);
}

.gr-match__why {
	font-size: 0.75rem;
	line-height: 1.35;
}

.gr-living-style__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	margin: 1.25rem 0 0;
}

/* --- Profile image upload fields ---------------------------------------- */

.gr-media-field__row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1.25rem;
	margin-top: 0.5rem;
}

.gr-media-preview {
	flex: 0 0 auto;
	width: 8rem;
	height: 8rem;
	/*
	 * Round, because the profile photo is round. A square preview of a
	 * circular crop is a preview of something the member never sees.
	 */
	border-radius: 50%;
	border: 1px solid var(--gr-border);
	background: var(--gr-bg-subtle);
	overflow: hidden;
	display: block;
}

/* The cover preview is the shape of the banner it becomes -- 4:1, matching
   .gr-profile__cover -- so what a member sees here is what the crop will do
   to their image. */
.gr-media-preview--cover {
	width: 20rem;
	max-width: 100%;
	height: 5rem;
	border-radius: var(--gr-radius);
}

/*
 * Two selectors deep on purpose. ComunityQ emits an inline
 * `.entry-content img { height: 300px }` from its media settings, which ties
 * with a single-class rule here on specificity and wins on order -- so the
 * preview images rendered 300px tall inside a 96px box, showing a top slice
 * of the picture with the face cut off. That is the "not centred, looks
 * strange" everyone sees. Adding the parent class outranks it without
 * resorting to !important, which would have to be undone by any theme that
 * later wants a say.
 */
.gr-media-field .gr-media-preview img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	display: block;
}

.gr-media-preview__empty {
	display: block;
	width: 100%;
	height: 100%;
	background: repeating-linear-gradient(45deg, var(--gr-bg-subtle) 0 8px, var(--gr-bg) 8px 16px);
}

.gr-media-field__controls {
	flex: 1 1 14rem;
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
	min-width: 0;
}

/*
 * The native file input is hidden and its label styled in its place. It stays
 * a real <input type="file"> inside its own <label>, so clicking the button and
 * tabbing to it both still work without a line of script -- this is
 * presentation only, not a replacement control.
 */
.gr-media-choose {
	position: relative;
	display: inline-flex;
	align-self: flex-start;
	cursor: pointer;
}

.gr-media-choose input[type="file"] {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	overflow: hidden;
}

.gr-media-choose__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 2.75rem;
	padding: 0.5rem 1.1rem;
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-btn-radius);
	background: var(--gr-bg-subtle);
	color: var(--gr-text);
	font-weight: 600;
	font-size: 0.9375rem;
}

.gr-media-choose:hover .gr-media-choose__button {
	border-color: var(--gr-accent);
}

.gr-media-choose:focus-within .gr-media-choose__button {
	outline: 2px solid var(--gr-accent);
	outline-offset: 2px;
}

.gr-media-remove {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	min-height: 2.75rem;
	font-size: 0.875rem;
	cursor: pointer;
}

.gr-profile__header {
	display: flex;
	flex-wrap: wrap;
	gap: 1.5rem;
	align-items: flex-start;
	padding: 1.5rem;
	background: var(--gr-bg-subtle);
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-radius);
	color: var(--gr-text);
}

/* With a cover above it, the header is the bottom half of one card rather
   than a box in its own right. */
.gr-profile--has-cover .gr-profile__header {
	border-top-left-radius: 0;
	border-top-right-radius: 0;
	border-top-color: transparent;
}

.gr-profile__avatar {
	flex: 0 0 auto;
}

/*
 * The avatar rides up over the cover's bottom edge -- the arrangement every
 * profile on the internet uses, and the reason is that it ties the two images
 * into one object instead of leaving a photo stranded above a box. Only when
 * there is a cover to ride up over; without one it sits normally.
 */
.gr-profile--has-cover .gr-profile__avatar {
	margin-top: -4rem;
}

.gr-profile__photo {
	width: 128px;
	height: 128px;
	object-fit: cover;
	border-radius: 50%;
	display: block;
	/* A ring in the surface colour, so the circle stays legible against
	   whatever photograph happens to be behind it. */
	border: 4px solid var(--gr-bg-subtle);
	background: var(--gr-bg-subtle);
}

@media (max-width: 575.98px) {
	/* Less overlap on a phone: at 4rem the avatar covers most of a cover that
	   is already only 5:2 there. */
	.gr-profile--has-cover .gr-profile__avatar {
		margin-top: -2.5rem;
	}
}

/* --- Badges beside the name --------------------------------------------- */

.gr-profile__badges {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.4rem;
	margin: 0 0 0.5rem;
}

/*
 * The verified badge carries an icon as well as the word, so it is never
 * colour alone -- and it reads as an earned mark rather than another chip.
 */
.gr-badge {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	padding: 0.15rem 0.55rem;
	border-radius: 999px;
	font-size: 0.78rem;
	font-weight: 700;
	line-height: 1.4;
}

.gr-badge--verified {
	background: #e7f6e7;
	border: 1px solid #bfe5bf;
	color: #14620f;
}

.gr-profile__identity {
	flex: 1 1 18rem;
	min-width: 0;
}

.gr-profile__name {
	margin: 0 0 0.25rem;
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.5rem;
	color: var(--gr-text);
}

.gr-profile__pronouns {
	font-size: 0.875rem;
	font-weight: 400;
	color: var(--gr-muted);
}

.gr-profile__headline {
	margin: 0 0 0.5rem;
	color: var(--gr-text);
}

.gr-profile__meta {
	list-style: none;
	margin: 0 0 0.75rem;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem 1rem;
	font-size: 0.9rem;
	color: var(--gr-muted);
}

/* Retained for themes overriding the profile template with the older markup;
   the shipped template now uses .gr-badge--verified in the name block. */
.gr-profile__verified {
	color: var(--gr-accent);
	font-weight: 600;
}

.gr-profile__roles,
.gr-member-card__roles {
	display: flex;
	flex-wrap: wrap;
	gap: 0.375rem;
	margin: 0 0 0.5rem;
}

.gr-profile__actions {
	margin: 0.75rem 0 0;
}

.gr-profile__section {
	margin-top: 2rem;
}

.gr-profile__section-title {
	margin: 0 0 1rem;
	font-size: 1.25rem;
	color: var(--gr-text);
}

.gr-profile__bio {
	color: var(--gr-text);
	line-height: 1.65;
}

.gr-profile__bio p:last-child {
	margin-bottom: 0;
}

/* Facts read as a definition list because that is what they are: a label and
 * its value. Grid rather than float so a missing fact leaves no hole. */
.gr-profile__facts {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
	gap: 1rem;
	margin: 0;
	padding: 1.25rem;
	background: var(--gr-bg-subtle);
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-radius);
}

.gr-profile__fact dt {
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--gr-muted);
	margin-bottom: 0.2rem;
}

.gr-profile__fact dd {
	margin: 0;
	font-weight: 600;
	color: var(--gr-text);
}

.gr-profile__section--contact {
	padding-top: 1rem;
	border-top: 1px solid var(--gr-border);
}

/* --- Member card ---------------------------------------------------------
 *
 * The photo is the card, the same way it is on a listing card -- a full-bleed
 * square rather than a small centred avatar with padding around it, so a
 * visitor scanning the grid is looking at faces first. Everything below it
 * (.gr-card__body) is deliberately compact: less padding, smaller type, a
 * one-line clamp on the headline, so the text stays a caption under the photo
 * instead of competing with it for space.
 */

.gr-member-card {
	text-align: center;
}

.gr-member-card__media {
	position: relative;
	aspect-ratio: 1 / 1;
	overflow: hidden;
	background: var(--gr-bg-subtle);
}

/*
 * Overrides the profile page's 128px circular .gr-profile__photo -- same
 * class, different context. Two classes beats one on specificity, so this
 * wins without needing !important.
 */
.gr-member-card__media .gr-profile__photo {
	width: 100%;
	height: 100%;
	margin: 0;
	border-radius: 0;
	object-fit: cover;
	object-position: center top;
	display: block;
}

.gr-member-card__verified {
	top: 0.6rem;
	right: 0.6rem;
}

.gr-member-card .gr-card__body {
	padding: 0.65rem 0.75rem 0.75rem;
	gap: 0.2rem;
}

.gr-member-card .gr-card__title {
	font-size: 0.95rem;
}

.gr-member-card__headline {
	margin: 0 0 0.3rem;
	font-size: 0.85rem;
	color: var(--gr-muted);
	/* One line: a long headline pushes the card taller than its photo, which
	   is the exact proportion this card is trying to avoid. */
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.gr-member-card .gr-card__location {
	font-size: 0.85rem;
}

.gr-member-card__roles {
	justify-content: center;
	margin: 0.2rem 0 0.3rem;
}

.gr-member-card__roles .gr-chip {
	font-size: 0.7rem;
	padding: 0.2rem 0.55rem;
}

.gr-member-card__actions {
	margin: 0.6rem 0 0;
}

.gr-member-card__actions .gr-btn {
	padding: 0.5rem 1rem;
	font-size: 0.875rem;
}

/* --- Edit form ----------------------------------------------------------- */

.gr-profile-form .gr-budget-pair,
.gr-profile-form .gr-field-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
	gap: 1rem;
}

@media (max-width: 40rem) {
	.gr-profile__header {
		flex-direction: column;
		align-items: center;
		text-align: center;
	}

	.gr-profile__name,
	.gr-profile__meta,
	.gr-profile__roles {
		justify-content: center;
	}
}

/* ---------------------------------------------------------------------------
 * Single listing
 *
 * Self-contained --gr-* block on .gr-single, same as .gr-archive and
 * .gr-listing-form above: a single listing page has neither of those as an
 * ancestor, and every rule below leans on these tokens with no literal
 * fallback of its own.
 * ------------------------------------------------------------------------ */

.gr-single {
	--gr-bg: var(--cq-surface, #ffffff);
	--gr-bg-subtle: var(--cq-surface-2, #f9fafb);
	--gr-text: var(--cq-body-color, #111827);
	--gr-muted: var(--cq-muted, #6b7280);
	--gr-border: var(--cq-border, #e5e7eb);
	--gr-accent: var(--cq-primary, #7c3aed);
	--gr-on-accent: var(--cq-on-primary, #ffffff);
	--gr-radius: var(--cq-container-radius, 8px);
	--gr-btn-radius: var(--cq-button-radius, 6px);

	color: var(--gr-text);
	max-width: 68rem;
	margin: 0 auto 3rem;
}

/* --- Gallery: main photo, filmstrip of thumbnails below --------------------
 *
 * Full-width main image on top, thumbnails in a tiled strip underneath --
 * square, edge to edge, no gap between them. Nothing here scrolls: a listing
 * with more than nine extra photos shows a "+N" count on the last thumbnail
 * instead of growing or clipping.
 */
.gr-gallery {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	margin-bottom: 1.5rem;
}

.gr-gallery__main {
	/*
	 * 4/3 on a 68rem-wide listing renders up to 816px tall -- nearly a full
	 * square of screen before you reach any actual listing details. 16/9
	 * caps it at 612px at that same width, which reads as a header rather
	 * than a wall.
	 */
	aspect-ratio: 16 / 9;
	/*
	 * And a ceiling in viewport terms as well as page terms. 16/9 alone still
	 * gave a 693px hero, which on a laptop meant the title, the price and the
	 * facts all began below the fold -- the picture had the whole first
	 * screen to itself. The aspect ratio keeps the shape; this stops it
	 * taking the screen.
	 */
	max-height: 55vh;
	border-radius: var(--gr-radius);
	overflow: hidden;
	background: var(--gr-bg-subtle);
}

.gr-gallery__main-link {
	display: block;
	width: 100%;
	height: 100%;
}

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

.gr-gallery__thumbs {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr));
	gap: 0;
	border-radius: var(--gr-radius);
	overflow: hidden;
}

.gr-gallery__thumb {
	position: relative;
	display: block;
	aspect-ratio: 1 / 1;
	overflow: hidden;
	background: var(--gr-bg-subtle);
	line-height: 0;
	box-shadow: inset 0 0 0 2px transparent;
}

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

.gr-gallery__thumb-more {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(17, 24, 39, 0.55);
	color: #ffffff;
	font-weight: 700;
	font-size: 0.9rem;
}

.gr-gallery__thumb.is-active {
	box-shadow: inset 0 0 0 2px var(--gr-accent);
	z-index: 1;
}

.gr-gallery__thumb:focus-visible {
	outline: 2px solid var(--gr-accent);
	outline-offset: -2px;
	z-index: 1;
}

.gr-gallery--empty .gr-card__placeholder {
	display: block;
	aspect-ratio: 16 / 9;
	border-radius: var(--gr-radius);
}

/* --- Listing body ---------------------------------------------------------- */

.gr-single__header {
	margin-bottom: 1rem;
}

.gr-single__badge {
	position: static;
	display: inline-block;
	margin-bottom: 0.5rem;
	border: 1px solid var(--gr-border);
}

.gr-single__title {
	margin: 0 0 0.25rem;
	color: var(--gr-text);
}

.gr-single__location {
	margin: 0;
	color: var(--gr-muted);
}

.gr-single__facts {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 1rem 0;
	padding: 0;
	font-weight: 600;
}

/*
 * Outlined chips, not solid orange.
 *
 * Orange earns its place on a listing card, where it is the thing that makes
 * one card distinguishable from the next in a grid. On the listing page there
 * is only one listing, so it identifies nothing -- and it landed directly
 * under the purple price band, two saturated brand colours arguing over a row
 * of plain facts. Quiet chips let the price stay the loudest thing on the
 * page, which is what a renter is looking for.
 */
.gr-single__facts li {
	background: var(--gr-bg-subtle);
	color: var(--gr-text);
	border: 1px solid var(--gr-border);
	padding: 0.35rem 0.85rem;
	border-radius: var(--gr-btn-radius);
}

.gr-single__section {
	margin-top: 1.75rem;
}

.gr-single__section-title {
	margin: 0 0 0.75rem;
	font-size: 1.1rem;
	color: var(--gr-text);
}

.gr-single__amenities {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
}

.gr-single__description {
	color: var(--gr-text);
	line-height: 1.65;
}

/* A rule above it, and more breathing room than the other sections get, so
   it reads as "here's where the listing itself ends" before the page moves
   on to other people's listings. */
.gr-single__related {
	margin-top: 2.5rem;
	padding-top: 1.75rem;
	border-top: 1px solid var(--gr-border);
}

/*
 * Price and Save, in the listing flow rather than a sidebar -- see the
 * template for why. Same brand purple as the primary button, so it reads as
 * "the key facts" the way the old sidebar card did, just inline instead
 * of beside everything else.
 */
.gr-single__price-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	margin: 1rem 0;
	padding: 1rem 1.25rem;
	background: linear-gradient(135deg, #7c2bc4 0%, #9c3bd3 100%);
	border: 1px solid transparent;
	border-radius: var(--gr-radius);
	color: #ffffff;
}

.gr-single__price {
	margin: 0;
	font-size: 1.4rem;
	color: #ffffff;
}

.gr-single__price-row .gr-card__period {
	color: rgba(255, 255, 255, 0.85);
}

.gr-single__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem;
}

/*
 * Overrides the card version of .gr-favorite, which is absolutely
 * positioned over a photo and icon-only. Here it is a normal in-flow button
 * with a label -- same class, same click handler, same is-favorited colour
 * rule, different chrome.
 */
.gr-single__favorite {
	position: static;
	width: auto;
	height: auto;
	padding: 0.65rem 1rem;
	border-radius: var(--gr-btn-radius);
	background: var(--gr-bg);
	border: 1px solid var(--gr-border);
	gap: 0.5rem;
	font-weight: 600;
	font-size: 0.925rem;
}

.gr-single__favorite.is-favorited {
	border-color: #d6336c;
}

/* Contact trigger sits next to Save, same row, same button rhythm. */
.gr-single__contact-trigger {
	padding: 0.65rem 1rem;
	font-size: 0.925rem;
}

/*
 * Facts on the left, host link on the right, one row. Wraps to two lines on
 * narrow screens rather than forcing the host link to shrink into the fact
 * list.
 */
.gr-single__meta-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem 1rem;
}

.gr-single__meta-row .gr-single__facts {
	margin: 0;
	flex: 1 1 auto;
}

/* --- Who is renting it out ---------------------------------------------- */

.gr-single__hostcard {
	display: flex;
	align-items: center;
	gap: 0.9rem;
	margin-top: 1.25rem;
	padding: 0.9rem 1.1rem;
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-radius);
	background: var(--gr-bg);
}

.gr-single__hostcard-photo {
	flex: 0 0 auto;
	display: block;
	line-height: 0;
}

.gr-single__hostcard-photo img {
	width: 3.5rem;
	height: 3.5rem;
	border-radius: 50%;
	object-fit: cover;
	display: block;
}

.gr-single__hostcard-body {
	flex: 1 1 auto;
	min-width: 0;
}

.gr-single__hostcard-body p {
	margin: 0;
}

.gr-single__hostcard-label {
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--gr-muted);
}

.gr-single__hostcard-name {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-top: 0.15rem !important;
	font-size: 1.0625rem;
	font-weight: 700;
}

.gr-single__hostcard-name a {
	color: var(--gr-text);
	text-decoration: none;
	overflow-wrap: anywhere;
}

.gr-single__hostcard-name a:hover,
.gr-single__hostcard-name a:focus-visible {
	color: var(--gr-accent);
	text-decoration: underline;
}

.gr-single__hostcard-meta {
	margin-top: 0.15rem !important;
	font-size: 0.8125rem;
	color: var(--gr-muted);
}

/* Colour stated, not inherited: on a theme that does not set link colour
   this rendered as default browser blue in the middle of a purple page. */
.gr-single__hostcard-link {
	flex: 0 0 auto;
	align-self: center;
	min-height: 2.75rem;
	display: inline-flex;
	align-items: center;
	padding: 0 0.25rem;
	color: var(--gr-accent);
	font-weight: 600;
	white-space: nowrap;
}

@media (max-width: 575.98px) {
	.gr-single__hostcard {
		flex-wrap: wrap;
	}

	/* Full width on its own line rather than a 40px stub beside the name. */
	.gr-single__hostcard-link {
		flex: 1 0 100%;
		justify-content: center;
		border-top: 1px solid var(--gr-border);
		padding-top: 0.5rem;
	}
}

/* --- Contact-the-host form --------------------------------------------- */

.gr-contact-form {
	max-width: 34rem;
}

.gr-contact-form textarea {
	resize: vertical;
}

/*
 * Hidden with CSS, not markup or display:none -- a bot scripted to skip
 * hidden inputs still finds and fills a field that is merely moved off
 * screen, which is the entire point of a honeypot. Sighted users never see
 * it; screen readers get aria-hidden on the wrapper as a second signal.
 */
.gr-hp-field {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* --------------------------------------------------------------------------
   Sidebar widgets
   -------------------------------------------------------------------------- */

/*
 * Widgets sit in the theme's sidebar column, outside any .gr-archive or
 * .gr-listing-form scope, so the token set has to be declared here too --
 * that is the whole lesson from the 1.16:1 incident noted at the top of this
 * file. Same tokens, same source, one more place that resolves them.
 */
.gr-widget {
	--gr-bg: var(--cq-surface, #ffffff);
	--gr-bg-subtle: var(--cq-surface-2, #f9fafb);
	--gr-text: var(--cq-body-color, #111827);
	--gr-muted: var(--cq-muted, #6b7280);
	--gr-border: var(--cq-border, #e5e7eb);
	--gr-accent: var(--cq-primary, #7c3aed);
	--gr-on-accent: var(--cq-on-primary, #ffffff);
	--gr-radius: var(--cq-container-radius, 8px);
	--gr-btn-radius: var(--cq-button-radius, 6px);

	color: var(--gr-text);
	font-size: 0.9375rem;
}

.gr-widget__title {
	margin: 0 0 0.85rem;
	font-size: 1.0625rem;
	color: var(--gr-text);
}

.gr-widget .gr-btn {
	width: 100%;
	min-height: 2.75rem;
}

.gr-widget-empty {
	margin: 0 0 0.85rem;
	color: var(--gr-muted);
	line-height: 1.6;
}

/* --- Nav lists ---------------------------------------------------------- */

.gr-widget-nav {
	list-style: none;
	margin: 0;
	padding: 0;
}

/*
 * The row is the flex container, not the link. The count is a sibling of the
 * anchor -- it must not be inside it, or a screen reader reads "Saved
 * listings 3" as the link text -- and a non-flex row drops it onto a line of
 * its own.
 */
.gr-widget-nav__item {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

.gr-widget-nav__item + .gr-widget-nav__item {
	border-top: 1px solid var(--gr-border);
}

/*
 * 44px rows rather than the 24px WCAG 2.2 asks for at AA. These are the
 * primary navigation on a phone, where a row you have to aim at is a row
 * people mis-tap, and the extra height costs nothing in a column nobody
 * scrolls for its own sake.
 */
.gr-widget-nav__link {
	flex: 1 1 auto;
	display: flex;
	align-items: center;
	gap: 0.5rem;
	min-width: 0;
	min-height: 2.75rem;
	padding: 0.6rem 0;
	color: var(--gr-text);
	text-decoration: none;
	font-weight: 500;
}

.gr-widget-nav__link:hover,
.gr-widget-nav__link:focus-visible {
	color: var(--gr-accent);
	text-decoration: underline;
}

.gr-widget-nav__link--primary {
	font-weight: 700;
	color: var(--gr-accent);
}

/* A count, not a label -- it has to read as secondary to the link it follows. */
.gr-widget-nav__note {
	flex: 0 0 auto;
	min-width: 1.5rem;
	padding: 0.1rem 0.45rem;
	border-radius: 999px;
	background: var(--gr-bg-subtle);
	color: var(--gr-muted);
	font-size: 0.75rem;
	font-weight: 700;
	text-align: center;
}

/* --- Filter form -------------------------------------------------------- */

.gr-widget-filters__field {
	display: block;
	margin: 0 0 0.75rem;
}

.gr-widget-filters__field label {
	display: block;
	margin-bottom: 0.25rem;
	font-size: 0.8125rem;
	font-weight: 600;
	color: var(--gr-muted);
}

.gr-widget-filters__field input,
.gr-widget-filters__field select {
	width: 100%;
	padding: 0.55rem 0.65rem;
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-radius);
	background: var(--gr-bg);
	color: var(--gr-text);
	font: inherit;
	font-size: 0.9375rem;
}

.gr-widget-filters__field input:focus-visible,
.gr-widget-filters__field select:focus-visible {
	outline: 2px solid var(--gr-accent);
	outline-offset: 1px;
}

.gr-widget-filters__row {
	display: flex;
	gap: 0.5rem;
}

.gr-widget-filters__row .gr-widget-filters__field {
	flex: 1 1 0;
	min-width: 0;
}

.gr-widget-filters__group {
	margin: 0 0 0.75rem;
	padding: 0;
	border: 0;
}

.gr-widget-filters__group legend {
	margin-bottom: 0.35rem;
	padding: 0;
	font-size: 0.8125rem;
	font-weight: 600;
	color: var(--gr-muted);
}

.gr-widget-filters__check {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	min-height: 2rem;
	line-height: 1.35;
	cursor: pointer;
}

.gr-widget-filters__check input {
	flex: 0 0 auto;
	width: 1rem;
	height: 1rem;
	margin: 0;
	accent-color: var(--gr-accent);
}

.gr-widget-filters__submit {
	margin: 1rem 0 0;
}

.gr-widget-filters__clear {
	margin: 0.6rem 0 0;
	text-align: center;
	font-size: 0.8125rem;
}

/* --- Listing actions ---------------------------------------------------- */

.gr-widget-actions {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
}

.gr-widget-actions__note {
	margin: 0;
	color: var(--gr-muted);
	font-size: 0.875rem;
}

/*
 * The sidebar save button is the same .gr-favorite the card uses, so it
 * inherits the icon colour and is-favorited rules. Only the shape changes:
 * full width with its label beside the heart, rather than a floating circle
 * over a photo.
 */
.gr-favorite.gr-widget-actions__save {
	position: static;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	width: 100%;
	min-height: 2.75rem;
	padding: 0.7rem 1rem;
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-btn-radius);
	background: var(--gr-bg);
	color: var(--gr-text);
	font-weight: 600;
	box-shadow: none;
}

.gr-favorite.gr-widget-actions__save:hover,
.gr-favorite.gr-widget-actions__save:focus-visible {
	border-color: var(--gr-accent);
	color: var(--gr-accent);
}

.gr-widget-actions__report {
	margin: 0.2rem 0 0;
	text-align: center;
	font-size: 0.8125rem;
}

.gr-widget-actions__report a {
	color: var(--gr-muted);
}

/* --- Host card ---------------------------------------------------------- */

.gr-host-card__identity {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin-bottom: 0.9rem;
}

.gr-host-card__photo img {
	width: 3.25rem;
	height: 3.25rem;
	border-radius: 50%;
	object-fit: cover;
	display: block;
}

.gr-host-card__names {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.25rem;
	min-width: 0;
}

.gr-host-card__name {
	font-weight: 700;
	color: var(--gr-text);
	text-decoration: none;
	overflow-wrap: anywhere;
}

.gr-host-card__facts {
	margin: 0 0 0.85rem;
}

.gr-host-card__fact {
	display: flex;
	justify-content: space-between;
	gap: 0.75rem;
	padding: 0.4rem 0;
	border-top: 1px solid var(--gr-border);
	font-size: 0.875rem;
}

.gr-host-card__fact dt {
	color: var(--gr-muted);
	font-weight: 500;
}

.gr-host-card__fact dd {
	margin: 0;
	text-align: right;
	font-weight: 600;
}

.gr-host-card__link {
	margin: 0;
	font-size: 0.875rem;
}

/* --- Match score -------------------------------------------------------- */

.gr-match-widget__score {
	margin: 0 0 0.5rem;
	text-align: center;
}

.gr-match-widget__number {
	font-size: 2.6rem;
	font-weight: 800;
	line-height: 1;
	color: var(--gr-accent);
}

.gr-match-widget--high .gr-match-widget__number {
	color: #116329;
}

.gr-match-widget--low .gr-match-widget__number {
	color: var(--gr-muted);
}

.gr-match-widget__pct {
	font-size: 1.1rem;
	font-weight: 700;
	margin-left: 0.1rem;
}

.gr-match-widget__meter,
.gr-completion__meter {
	height: 0.5rem;
	margin: 0 0 0.9rem;
	border-radius: 999px;
	background: var(--gr-bg-subtle);
	overflow: hidden;
}

.gr-match-widget__meter span,
.gr-completion__meter span {
	display: block;
	height: 100%;
	border-radius: inherit;
	background: var(--gr-accent);
}

.gr-match-widget--high .gr-match-widget__meter span {
	background: #116329;
}

.gr-match-widget__reasons,
.gr-completion__missing {
	list-style: none;
	margin: 0 0 0.9rem;
	padding: 0;
	font-size: 0.875rem;
	line-height: 1.5;
	color: var(--gr-muted);
}

.gr-match-widget__reasons li,
.gr-completion__missing li {
	position: relative;
	padding: 0.2rem 0 0.2rem 1.1rem;
}

.gr-match-widget__reasons li::before,
.gr-completion__missing li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.7rem;
	width: 0.35rem;
	height: 0.35rem;
	border-radius: 50%;
	background: var(--gr-accent);
}

.gr-match-widget__budget {
	margin: 0 0 0.9rem;
	font-size: 0.875rem;
	color: var(--gr-muted);
}

.gr-match-widget__links,
.gr-widget-more {
	margin: 0 0 0.6rem;
	font-size: 0.875rem;
}

.gr-match-widget__prompt {
	margin: 0 0 0.85rem;
	color: var(--gr-muted);
	line-height: 1.6;
}

/* --- Match list --------------------------------------------------------- */

.gr-match-list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.gr-match-list__item + .gr-match-list__item {
	border-top: 1px solid var(--gr-border);
}

.gr-match-list__link {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	min-height: 2.75rem;
	padding: 0.5rem 0;
	color: var(--gr-text);
	text-decoration: none;
}

.gr-match-list__photo img {
	width: 2.25rem;
	height: 2.25rem;
	border-radius: 50%;
	object-fit: cover;
	display: block;
}

.gr-match-list__name {
	flex: 1 1 auto;
	min-width: 0;
	font-weight: 600;
	overflow-wrap: anywhere;
}

.gr-match-list__score {
	flex: 0 0 auto;
	padding: 0.15rem 0.5rem;
	border-radius: 999px;
	background: var(--gr-bg-subtle);
	color: var(--gr-accent);
	font-size: 0.8125rem;
	font-weight: 700;
}

.gr-match-list__score--high {
	background: #e6f4ea;
	color: #116329;
}

/* --- Completion --------------------------------------------------------- */

.gr-completion__figure {
	margin: 0 0 0.5rem;
	font-weight: 700;
}

/* --- Simple lists ------------------------------------------------------- */

.gr-widget-list {
	list-style: none;
	margin: 0 0 0.6rem;
	padding: 0;
}

.gr-widget-list__item {
	padding: 0.5rem 0;
	line-height: 1.4;
}

.gr-widget-list__item + .gr-widget-list__item {
	border-top: 1px solid var(--gr-border);
}

.gr-widget-list__item a {
	color: var(--gr-text);
	font-weight: 600;
	text-decoration: none;
	overflow-wrap: anywhere;
}

.gr-widget-list__meta {
	display: block;
	margin-top: 0.15rem;
	color: var(--gr-muted);
	font-size: 0.8125rem;
}

/* --- Safety ------------------------------------------------------------- */

.gr-widget-safety {
	list-style: none;
	margin: 0;
	padding: 0;
	font-size: 0.875rem;
	line-height: 1.55;
	color: var(--gr-text);
}

.gr-widget-safety li {
	position: relative;
	padding: 0.4rem 0 0.4rem 1.4rem;
}

.gr-widget-safety li + li {
	border-top: 1px solid var(--gr-border);
}

/* An exclamation set in CSS, so no icon font and nothing to load. */
.gr-widget-safety li::before {
	content: "!";
	position: absolute;
	left: 0;
	top: 0.55rem;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 1rem;
	height: 1rem;
	border-radius: 50%;
	background: var(--gr-orange, #c2410c);
	color: #ffffff;
	font-size: 0.65rem;
	font-weight: 800;
	line-height: 1;
}

/* --------------------------------------------------------------------------
   Service directory
   -------------------------------------------------------------------------- */

.gr-services,
.gr-service,
.gr-service-dashboard {
	--gr-bg: var(--cq-surface, #ffffff);
	--gr-bg-subtle: var(--cq-surface-2, #f9fafb);
	--gr-text: var(--cq-body-color, #111827);
	--gr-muted: var(--cq-muted, #6b7280);
	--gr-border: var(--cq-border, #e5e7eb);
	--gr-accent: var(--cq-primary, #7c3aed);
	--gr-on-accent: var(--cq-on-primary, #ffffff);
	--gr-radius: var(--cq-container-radius, 8px);
	--gr-btn-radius: var(--cq-button-radius, 6px);

	color: var(--gr-text);
}

/* --- Badges ------------------------------------------------------------- */

/*
 * Three badges, three meanings, and they must not look interchangeable.
 * Pledged is the one no provider can award themselves, so it gets the
 * strongest treatment; LGBTQ+ owned is a confirmed fact about the business;
 * 24hr is practical information, not a trust signal, so it stays neutral.
 */
.gr-badge--pledge {
	background: #e6f4ea;
	color: #116329;
	border: 1px solid #116329;
}

.gr-badge--owned {
	background: #f3f0fb;
	color: #6920ad;
	border: 1px solid #6920ad;
}

.gr-badge--emergency {
	background: var(--gr-bg-subtle, #f9fafb);
	color: var(--gr-muted, #6b7280);
	border: 1px solid var(--gr-border, #e5e7eb);
}

/* --- Directory cards ---------------------------------------------------- */

.gr-services__flags {
	margin-top: 0.5rem;
}

.gr-service-card {
	background: var(--gr-bg);
	border: 1px solid var(--gr-border);
	border-radius: var(--gr-radius);
	overflow: hidden;
}

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

.gr-service-card__media {
	display: block;
	aspect-ratio: 16 / 9;
	background: var(--gr-bg-subtle);
	overflow: hidden;
}

.gr-service-card .gr-service-card__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	display: block;
}

.gr-service-card__body {
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
	padding: 0.9rem 1rem 1.1rem;
}

.gr-service-card__cat {
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--gr-muted);
}

.gr-service-card__name {
	font-size: 1.0625rem;
	font-weight: 700;
	line-height: 1.3;
	overflow-wrap: anywhere;
}

.gr-service-card__place,
.gr-service-card__creds {
	font-size: 0.8125rem;
	color: var(--gr-muted);
}

.gr-service-card__badges {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem;
	margin-top: 0.15rem;
}

.gr-service-card__badges:empty {
	display: none;
}

/* --- Provider page ------------------------------------------------------ */

.gr-service__media {
	border-radius: var(--gr-radius);
	overflow: hidden;
	margin-bottom: 1.25rem;
	aspect-ratio: 16 / 9;
	max-height: 45vh;
	background: var(--gr-bg-subtle);
}

.gr-service .gr-service__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	display: block;
}

.gr-service__badges {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	margin: 0.65rem 0 0;
}

.gr-service__badges:empty {
	display: none;
}

/*
 * The phone number is the primary action and is styled as one. Publishing it
 * is the point of a trade directory -- the opposite of the rule on a member
 * profile, where the same treatment would be a mistake.
 */
.gr-service__callrow {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem 1rem;
}

.gr-service__phone {
	flex: 1 1 auto;
	font-size: 1.5rem;
	font-weight: 800;
	color: #ffffff;
	text-decoration: none;
	letter-spacing: 0.01em;
	min-height: 2.75rem;
	display: inline-flex;
	align-items: center;
}

.gr-service__phone:hover,
.gr-service__phone:focus-visible {
	color: #ffffff;
	text-decoration: underline;
}

.gr-service__facts {
	margin-top: 1rem;
}

.gr-service__pledge-list {
	list-style: none;
	margin: 0;
	padding: 0;
	font-size: 0.9375rem;
	line-height: 1.6;
}

.gr-service__pledge-list li {
	position: relative;
	padding: 0.35rem 0 0.35rem 1.6rem;
}

.gr-service__pledge-list li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.75rem;
	width: 0.85rem;
	height: 0.45rem;
	border-left: 2px solid #116329;
	border-bottom: 2px solid #116329;
	transform: rotate(-45deg);
}

.gr-service__claim {
	border: 1px dashed var(--gr-border);
	border-radius: var(--gr-radius);
	padding: 1rem 1.25rem;
}

/*
 * Stated on every provider page rather than buried in a terms document. A
 * directory that lists a business is making an implicit endorsement, and the
 * honest thing is to say on the page that it is not one.
 */
.gr-service__disclaimer {
	margin-top: 2rem;
	padding-top: 1rem;
	border-top: 1px solid var(--gr-border);
	font-size: 0.8125rem;
	color: var(--gr-muted);
	line-height: 1.6;
}

/* --- Submission form ---------------------------------------------------- */

.gr-service-form__pledge-list {
	list-style: none;
	margin: 0 0 1rem;
	padding: 0;
	font-size: 0.9375rem;
	line-height: 1.6;
}

.gr-service-form__pledge-list li {
	padding: 0.4rem 0 0.4rem 1.1rem;
	border-left: 3px solid var(--gr-accent);
	padding-left: 0.85rem;
	margin-bottom: 0.4rem;
	background: var(--gr-bg-subtle);
}

/* Off-screen rather than display:none -- a bot that skips hidden inputs
   defeats a honeypot that hides them the obvious way. */
.gr-hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* --- Provider dashboard ------------------------------------------------- */

.gr-dashboard-list {
	list-style: none;
	margin: 0;
	padding: 0;
}

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

.gr-dashboard-item__title {
	margin: 0;
	font-weight: 700;
}

.gr-dashboard-item__title a {
	color: var(--gr-text);
	text-decoration: none;
}

.gr-dashboard-item__meta {
	margin: 0.15rem 0 0;
	font-size: 0.8125rem;
	color: var(--gr-muted);
}

.gr-dashboard-item__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0;
}

@media (max-width: 575.98px) {
	.gr-service__phone {
		font-size: 1.25rem;
		flex: 1 0 100%;
	}

	.gr-dashboard-item__actions {
		flex: 1 0 100%;
	}
}

/* --- Owner controls on a dashboard -------------------------------------- */

.gr-dashboard__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin: 0.6rem 0 0;
}

.gr-dashboard__actions .gr-btn {
	min-height: 2.75rem;
	padding-inline: 1rem;
	font-size: 0.875rem;
}

/*
 * Delete is a quiet text link beside two real buttons, not a third button.
 * The visual weight should match how often it is the right answer: somebody
 * whose room is filled wants Pause or Mark rented, and giving all three equal
 * prominence is how a listing gets destroyed when it only needed hiding.
 */
.gr-dashboard__delete,
.gr-dashboard__cancel {
	margin-left: auto;
	font-size: 0.875rem;
	color: var(--gr-muted, #6b7280);
	text-decoration: underline;
	min-height: 2.75rem;
	display: inline-flex;
	align-items: center;
}

.gr-dashboard__delete:hover,
.gr-dashboard__delete:focus-visible {
	color: #b32d2e;
}

.gr-dashboard__cancel {
	margin-left: 0.75rem;
}

.gr-dashboard__confirm {
	margin: 0.6rem 0 0;
	padding: 0.9rem 1.1rem;
	border: 1px solid #b32d2e;
	border-radius: var(--gr-radius, 8px);
	background: #fdf3f3;
}

.gr-dashboard__confirm p {
	margin: 0 0 0.5rem;
	font-size: 0.875rem;
	line-height: 1.5;
}

.gr-dashboard__confirm form {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	margin: 0;
}

/*
 * The only destructive button in the plugin, and the only place this colour
 * appears -- so it cannot be confused with the primary action anywhere else.
 */
.gr-btn--danger {
	background: #b32d2e;
	color: #ffffff;
	border: 1px solid #b32d2e;
	min-height: 2.75rem;
}

.gr-btn--danger:hover,
.gr-btn--danger:focus-visible {
	background: #8f2324;
	border-color: #8f2324;
	color: #ffffff;
}

@media (max-width: 575.98px) {
	.gr-dashboard__delete {
		margin-left: 0;
	}
}
