/* GDV Client Reviews — public.css */

/* ================================================
   Review panel

   The shortcode draws a panel: a score at the head saying what every published
   review averages and how many there are, then the reviews themselves. The
   score is the credibility: a visitor reading three quotes has no way to know
   whether they are three out of four or three out of forty, and the head of
   the panel answers that before the first quote is read.

   The audience is professional, and the panel is drawn for it. The stars, the
   figure and the count appear once, in the head. A card carries the quote in
   the site's serif, and under it the person: the name, what they do and where,
   and which talk or course the review is about. No stars per card, no badge,
   no avatar, no shadow and no hover: those are the anatomy of a marketplace
   listing, and on a page of considered testimonials they read as a scoreboard.

   Colours come from gdv-public-ui's --gdv-ui-* tokens, each with its light-mode
   value as the fallback for a page where the library is absent. The tokens
   declared on the panel are the plugin's own, because gdv-public-ui publishes
   no star colour and no quote face.
   ================================================ */

.gdv-cr-panel {
	/* The filled star's edge. The brand yellow is 2.04:1 on white, which is
	   below the 3:1 a meaningful graphic needs, so the star carries a darker
	   gold outline that does the contrast work: #8a6100 is 5.54:1 on white.
	   In dark mode the yellow itself is 7.89:1 on #212121 and needs no help,
	   so the edge becomes the fill colour and disappears. */
	--gdv-cr-star:        var(--gdv-ui-primary, #e1ad4e);
	--gdv-cr-star-edge:   #8a6100;
	--gdv-cr-star-empty:  var(--gdv-ui-border-strong, #797979);

	/* The quote's face. A theme that has a heading serif sets this token on
	   the panel, and the quote then matches the page's titles; without it
	   the quote falls back to the system serif. */
	--gdv-cr-quote-font:  Georgia, "Times New Roman", serif;

	margin: 0 0 2rem;
	color: var(--gdv-ui-text, #444444);
}

@media (prefers-color-scheme: dark) {
	.gdv-cr-panel {
		--gdv-cr-star-edge:   var(--gdv-ui-primary, #e1ad4e);
	}
}

/* Panel head: the score, and nothing else below 48rem. The invitation is drawn
   after the reviews there, because a question about writing one is worth
   answering once some have been read, and on a phone that is where the reader
   is. From 48rem up the two sit side by side again, which is what the grid at
   the foot of this section does.

   No rule under the head on a phone: the first card carries its own border a
   few pixels below, so the line reads as a second frame around nothing. */

.gdv-cr-panel__head {
	display: flex;
	flex-direction: column;
	gap: 1.25rem;
	margin-bottom: 1.5rem;
}

/* The three lines are paragraphs, and on an article the theme gives every
   paragraph in the content 1.2em of bottom margin at a weight a single class
   cannot beat. Their spacing is the flex gap of the block they sit in, so the
   margin is put back to zero here rather than in each rule below. */
.gdv-cr-panel .gdv-cr-panel__head p.gdv-cr-score__figure,
.gdv-cr-panel .gdv-cr-panel__head p.gdv-cr-score__count,
.gdv-cr-panel .gdv-cr-invites p.gdv-cr-invite {
	margin: 0;
}

/* The figure, the stars and the count on one line: a fact stated once, not a
   hero number. They wrap to two lines only where the width forces it. */
.gdv-cr-score {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.25rem 0.75rem;
}

.gdv-cr-score__figure {
	display: flex;
	align-items: baseline;
	gap: 0.375rem;
	margin: 0;
}

/* 1.5rem at 600 is large text, and 9.74:1 on white. */
.gdv-cr-score__value {
	font-size: 1.5rem;
	font-weight: 600;
	line-height: 1;
	color: var(--gdv-ui-text, #444444);
}

.gdv-cr-score__max,
.gdv-cr-score__count {
	margin: 0;
	font-size: 0.9375rem;
	line-height: 1.4;
	color: var(--gdv-ui-text-faint, #666666);
}

/* The invitation: the question as a line, then the two ways on as underlined
   text links, one under the other. Links at every width: a filled control in
   a panel of reviews outranks the reviews themselves, which is what the
   visitor came to read.

   Each link is a flex item, so it is block-level whatever its display value,
   and the vertical padding counts towards its height: 1rem at line-height 1.5
   is 24px, plus 2 x 10px, so the activation area is 44px tall on a phone and
   in the installed app while the link still reads as a line of text.

   The block is right-aligned only where it sits beside the score. Below that
   it follows the last card, centred under it. */

.gdv-cr-invites {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.625rem;
	margin-top: 1.5rem;
}

.gdv-cr-invites__row {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.25rem;
}

/* The hover state is restated because the theme paints every bare a:hover in
   the brand yellow, 2.04:1 on white. #444444 is 9.74:1 and stays put. */
.gdv-cr-panel .gdv-cr-invites__link,
.gdv-cr-panel .gdv-cr-invites__link:is(:hover, :focus, :active) {
	padding: 0.625rem 0;
	font-size: 1rem;
	font-weight: 400;
	line-height: 1.5;
	color: var(--gdv-ui-text, #444444);
	text-decoration: underline;
}

/* The ring is its own token because the brand yellow cannot serve as one.
   --gdv-ui-focus is 5.54:1 light and 7.89:1 dark. */
.gdv-cr-panel .gdv-cr-invites__link:focus-visible {
	outline: 2px solid var(--gdv-ui-focus, #8a6100);
	outline-offset: 2px;
}

/* From 48rem up the panel is a grid of two rows: the score and the invitation
   side by side above, the reviews across the full width below. The invitation
   is the last element in the markup and is placed into the top row here, so
   the phone gets the order it is written in and the wide screen the head it
   had. A screen reader and the tab key follow the markup at both widths, which
   is the reviews first and the question about writing one after them.

   The rule that closes the head off from the list is the list's own top border
   rather than the head's bottom one, because the head now covers half the
   width and the line has to run the whole of it.

   The links lose their vertical padding here: a pointer needs no 44px, and the
   head has to stay one row high beside the score. */
@media (min-width: 48rem) {
	.gdv-cr-panel {
		display: grid;
		/* minmax(0, 1fr), not 1fr: the score's own minimum width would
		   otherwise stop it wrapping and push the panel sideways at 768px. */
		grid-template-columns: minmax(0, 1fr) auto;
		align-items: center;
		column-gap: 2rem;
	}

	.gdv-cr-panel__head {
		grid-area: 1 / 1 / 2 / 2;
		margin-bottom: 1.25rem;
	}

	.gdv-cr-invites {
		grid-area: 1 / 2 / 2 / 3;
		align-items: flex-end;
		gap: 0.25rem;
		margin-top: 0;
		margin-bottom: 1.25rem;
	}

	/* section.gdv-cr-panel, because the list's own rule further down this file
	   sets padding: 0 at the same weight and comes after this one. A media
	   query adds nothing to specificity, so naming the section is what keeps
	   the padding-top here. */
	section.gdv-cr-panel ul.gdv-cr-list {
		grid-area: 2 / 1 / 3 / 3;
		padding-top: 1.5rem;
		border-top: 1px solid var(--gdv-ui-border, #d6d6d6);
	}

	.gdv-cr-invites__row {
		align-items: flex-end;
	}

	.gdv-cr-panel .gdv-cr-invites__link,
	.gdv-cr-panel .gdv-cr-invites__link:is(:hover, :focus, :active) {
		padding: 0;
	}
}

.gdv-cr-invite {
	margin: 0;
	font-size: 1rem;
	text-align: center;
	color: var(--gdv-ui-text, #444444);
}

/* The ring is its own token because the brand yellow is 2.04:1 on white and
   cannot serve as one. --gdv-ui-focus is 5.54:1 light and 7.89:1 dark. */
.gdv-cr-readmore:focus-visible {
	outline: 2px solid var(--gdv-ui-focus, #8a6100);
	outline-offset: 2px;
}

/* The cards. A grid rather than a flex row: every card in a row is the height
   of the tallest, so the names line up across the row whatever the length of
   the quotes above them, and a lone card does not stretch to a shape no other
   card ever takes. minmax(min(100%, 17.5rem), 1fr) is what keeps that true at
   320px, where 17.5rem alone would overflow the viewport.

   **Why these selectors name the element.** A shortcode in page content renders
   inside .nv-content-wrap, and the theme styles the lists in there by element:

     .nv-content-wrap ul      padding-left: 1em; margin: 1em 0
     .nv-content-wrap ul li   margin-top: 3px, and 1em under 767px

   Both are one class plus one element, which outranks a single class of ours.
   Left as a single class, the list took the theme's 1em left padding and the
   whole row of cards sat inset from the score above it on the left and flush on
   the right. Adding the element here lifts these two rules above the theme's
   without an !important and without naming the theme. */

.gdv-cr-panel ul.gdv-cr-list {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 17.5rem), 1fr));
	gap: 1.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* A plain white surface with a hairline edge. No shadow, no lift on hover:
   the card is a page, not a tile. */
.gdv-cr-panel li.gdv-cr-card {
	display: flex;
	flex-direction: column;
	margin: 0;
	/* A grid item's default minimum is its content, so one long word, URL or
	   e-mail address in a review would push the card wider than the column and
	   the page sideways with it. This pair is what holds at 320px. */
	min-width: 0;
	overflow-wrap: anywhere;
	padding: 1.5rem 1.625rem;
	color: var(--gdv-ui-text, #444444);
	background: var(--gdv-ui-surface, #ffffff);
	border: 1px solid var(--gdv-ui-border, #d6d6d6);
	border-radius: 4px;
	box-sizing: border-box;
}

/* A featured review is the one in a row of equals with a gold hairline.
   Nothing about the card's shape changes, so the row still reads as a row. */
.gdv-cr-panel li.gdv-cr-card--featured {
	border-color: var(--gdv-cr-star);
}

/* The quote itself, in the serif and a step above body size: the serif is what
   says "somebody said this", which the gold quote mark used to do.

   A <blockquote> is the right element and the theme paints one heavily: bare
   `blockquote` carries 1.3em type, 35px/45px padding, a 5% side margin and a
   giant green ::before quote mark, and Neve under it adds a 4px left border and
   max-width: 90%. Every one of those is reset here by name.

   The selector carries the element for the same reason the list above does: on
   an article the theme sets .single-gdv_article .nv-content-wrap blockquote to
   1.15em, which is one class more than a single class of ours can beat. */

.gdv-cr-panel .gdv-cr-card blockquote.gdv-cr-card__quote {
	display: block;
	position: static;
	flex: 1 1 auto;
	max-width: none;
	margin: 0 0 1.25rem;
	padding: 0;
	border: 0;
	font-family: var(--gdv-cr-quote-font);
	font-size: 1.0625rem;
	font-style: normal;
	font-weight: 400;
	line-height: 1.6;
	color: var(--gdv-ui-text, #444444);
}

.gdv-cr-panel .gdv-cr-card blockquote.gdv-cr-card__quote::before {
	content: none;
}

/* The dots and the link travel together and disappear together. An underline
   cannot be switched off on a descendant, so the dots sit outside the anchor
   rather than inside it wearing text-decoration: none. */
.gdv-cr-readmore-wrap[hidden] {
	display: none;
}

.gdv-cr-readmore {
	color: inherit;
	font-family: inherit;
	font-size: inherit;
	text-decoration: underline;
	white-space: nowrap;
}

/* Who said it, pushed to the foot of the card: the name, then what they do
   and where, then the caption line with the item reviewed and the date. */

.gdv-cr-card__by {
	display: flex;
	flex-direction: column;
	gap: 0.125rem;
	margin-top: auto;
	padding-top: 1rem;
	border-top: 1px solid var(--gdv-ui-border, #d6d6d6);
}

.gdv-cr-by__name {
	font-size: 1rem;
	font-weight: 600;
	color: var(--gdv-ui-text, #444444);
}

/* 0.9375rem is 15px, above the 13px floor for secondary text still read. */
.gdv-cr-by__role {
	font-size: 0.9375rem;
	line-height: 1.4;
	color: var(--gdv-ui-text, #444444);
}

.gdv-cr-by__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.125rem 0.75rem;
	margin-top: 0.25rem;
	font-size: 0.875rem;
	line-height: 1.4;
	color: var(--gdv-ui-text-faint, #666666);
}

/* Stars, drawn once in the head. An outline star with a filled copy clipped
   over it, so a half comes out as a half rather than as a rounded whole. The
   outline is what carries the empty state: 4.35:1 on white and 3.70:1 on
   #212121, both over the 3:1 a graphic needs.

   The star itself is drawn with rounded tips and notches (icons/star.svg), and
   the dark edge below is kept to a hairline. The gap gives the five room so
   they read as a rating rather than as a block. */

.gdv-cr-stars {
	display: inline-flex;
	align-items: center;
	gap: 0.1875rem;
	font-size: 1.125rem;
	line-height: 1;
	color: var(--gdv-cr-star-empty);
}

.gdv-cr-star {
	position: relative;
	display: block;
	width: 1em;
	height: 1em;
}

.gdv-cr-star svg {
	display: block;
	width: 1em;
	height: 1em;
}

.gdv-cr-star__fill {
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	width: 100%;
	overflow: hidden;
	color: var(--gdv-cr-star);
}

/* A hairline, not a rim: its job is to give the fill an edge that carries the
   3:1 a graphic needs, since the brand yellow alone is 2.04:1 on white. Any
   heavier and the star reads as outlined rather than as gold. */
.gdv-cr-star__fill svg {
	stroke: var(--gdv-cr-star-edge);
	stroke-width: 1.25;
}

.gdv-cr-star--half .gdv-cr-star__fill {
	width: 50%;
}

@media (max-width: 480px) {
	.gdv-cr-panel li.gdv-cr-card {
		padding: 1.25rem;
	}
}

/* ================================================
   Submit form

   Same card, sizes and field anatomy as gdv-event-manager's subscription
   form. Colours come from gdv-public-ui's --gdv-ui-* tokens (site-wide, with
   dark mode), each with the light-mode value as fallback for a site where
   the library is absent. The two tint tokens below are the plugin's own,
   because gdv-public-ui publishes no light tints.
   ================================================ */

.gdv-cr-form-wrapper {
	--gdv-cr-success-light: #e8f1f1;
	--gdv-cr-danger-light:  #fceceb;

	max-width: 40rem;
	/* The shortcode is the last thing on its page, so the card carries the
	   space between itself and the footer: nothing below it would. */
	margin: 0 auto 3rem;
	padding: 1.75rem;
	font-size: 1rem;
	line-height: 1.5;
	color: var(--gdv-ui-text, #444444);
	background: var(--gdv-ui-surface, #ffffff);
	border-radius: 8px;
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 4px 12px rgba(0, 0, 0, 0.06);
	box-sizing: border-box;
}

@media (prefers-color-scheme: dark) {
	.gdv-cr-form-wrapper {
		--gdv-cr-success-light: #1e3232;
		--gdv-cr-danger-light:  #3a2120;

		box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), 0 4px 12px rgba(0, 0, 0, 0.20);
	}
}

.gdv-cr-form-fieldset {
	border: 0;
	margin: 0;
	padding: 0;
	min-width: 0;
}

.gdv-cr-form-fieldset:disabled {
	opacity: 0.6;
}

/* Fields */

.gdv-cr-form__field {
	margin-bottom: 1.125rem;
}

.gdv-cr-form__field label,
.gdv-cr-form__label {
	display: block;
	font-size: 1rem;
	font-weight: 600;
	color: var(--gdv-ui-text, #444444);
	margin-bottom: 0.375rem;
}

.gdv-cr-required {
	color: var(--gdv-ui-danger, #b32d2e);
	margin-left: 2px;
}

.gdv-cr-form__field input[type="text"],
.gdv-cr-form__field input[type="email"],
.gdv-cr-form__field select,
.gdv-cr-form__field textarea {
	width: 100%;
	padding: 0.6875rem 0.875rem;
	border: 1px solid var(--gdv-ui-border-strong, #797979);
	border-radius: 4px;
	font-size: 1rem;
	font-family: inherit;
	line-height: 1.4;
	color: var(--gdv-ui-text, #444444);
	background: var(--gdv-ui-surface, #ffffff);
	box-sizing: border-box;
	transition: border-color 0.15s, box-shadow 0.15s;
}

.gdv-cr-form__field input[type="text"]:focus,
.gdv-cr-form__field input[type="email"]:focus,
.gdv-cr-form__field select:focus,
.gdv-cr-form__field textarea:focus {
	outline: 2px solid var(--gdv-ui-focus, #8a6100);
	outline-offset: 2px;
	border-color: var(--gdv-ui-primary, #e1ad4e);
}

.gdv-cr-form__field textarea {
	resize: vertical;
	min-height: 9rem;
}

.gdv-cr-form__field select {
	appearance: none;
	-webkit-appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7' viewBox='0 0 12 7'%3E%3Cpath fill='%23797979' d='M6 7L0 0h12z'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 0.875rem center;
	padding-right: 2.25rem;
	cursor: pointer;
}

.gdv-cr-field-hint,
.gdv-cr-char-counter {
	font-size: 0.875rem;
	color: var(--gdv-ui-text-faint, #666666);
	margin: 0.375rem 0 0;
	line-height: 1.4;
}

.gdv-cr-char-counter {
	text-align: right;
}

.gdv-cr-char-counter.gdv-cr-over-limit {
	color: var(--gdv-ui-danger, #b32d2e);
	font-weight: 600;
}

/* Error line: always in the flow, collapsed while empty, so a message
   appearing does not shift the field below it more than one line. */
.gdv-cr-field-error {
	display: block;
	min-height: 1.25rem;
	font-size: 0.9375rem;
	line-height: 1.25rem;
	color: var(--gdv-ui-danger, #b32d2e);
	margin-top: 0.25rem;
}

.gdv-cr-field-error:empty {
	min-height: 0;
	margin-top: 0;
}

/* Rating widget */

.gdv-cr-rating-widget {
	display: flex;
	gap: 0.15rem;
	margin: 0.15rem 0;
}

/* Each star is a <button>, so the theme's bare button rules reach it. Every
   rule below carries the widget class to outrank them.

   The star is the same lucide SVG the list draws, so one star shape serves the
   whole plugin. 44 x 44 is the front-end activation area: at the 2rem glyph and
   no padding this control used to render 32px tall, which is under the floor on
   a phone, and five of them at 44 still fit a 320px viewport. */
.gdv-cr-rating-widget .gdv-cr-rating-star {
	display: flex;
	align-items: center;
	justify-content: center;
	background: none;
	border: none;
	box-shadow: none;
	width: auto;
	min-width: 44px;
	min-height: 44px;
	cursor: pointer;
	font-size: 2rem;
	color: var(--gdv-ui-border-strong, #797979);
	padding: 0;
	margin: 0;
	line-height: 1;
	transition: color 0.1s;
}

.gdv-cr-rating-widget .gdv-cr-rating-star svg {
	display: block;
	width: 1em;
	height: 1em;
}

.gdv-cr-rating-widget .gdv-cr-rating-star.gdv-cr-rating-star--active {
	color: var(--gdv-ui-primary, #e1ad4e);
}

/* Hover preview, CSS only: every star up to the hovered one lights up, the
   ones after it go grey. Limited to devices with a real pointer so a touch
   does not leave a sticky preview behind. */
@media (hover: hover) {
	.gdv-cr-rating-widget:hover .gdv-cr-rating-star {
		color: var(--gdv-ui-primary, #e1ad4e);
	}

	.gdv-cr-rating-widget .gdv-cr-rating-star:hover ~ .gdv-cr-rating-star {
		color: var(--gdv-ui-border-strong, #797979);
	}
}

.gdv-cr-rating-widget .gdv-cr-rating-star:focus-visible {
	outline: 2px solid var(--gdv-ui-focus, #8a6100);
	outline-offset: 2px;
	border-radius: 2px;
}

/* Consent checkbox: inline layout, and a reset of the theme's toggle-switch
   styling so it renders as a plain checkbox. */
.gdv-cr-form .gdv-cr-checkbox-field {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 0.5rem;
}

.gdv-cr-form .gdv-cr-checkbox-field .gdv-cr-field-error {
	flex-basis: 100%;
}

/* The label shrinks and wraps beside the box instead of dropping under it. */
.gdv-cr-form .gdv-cr-checkbox-field label {
	display: block;
	flex: 1 1 0;
	min-width: 0;
	font-weight: 400;
	font-size: 1rem;
	line-height: 1.4;
	margin-bottom: 0;
	cursor: pointer;
}

.gdv-cr-form .gdv-cr-checkbox-field input[type="checkbox"] {
	appearance: checkbox;
	-webkit-appearance: checkbox;
	width: 16px;
	height: 16px;
	border-radius: 2px;
	background-color: transparent;
	position: static;
	cursor: pointer;
	transition: none;
	flex-shrink: 0;
	margin: 0.15rem 0 0;
	accent-color: var(--gdv-ui-primary, #e1ad4e);
}

.gdv-cr-form .gdv-cr-checkbox-field input[type="checkbox"]::before {
	display: none;
}

.gdv-cr-form .gdv-cr-checkbox-field label a {
	color: var(--gdv-ui-primary, #e1ad4e);
}

.gdv-cr-form .gdv-cr-checkbox-field label a:hover {
	color: var(--gdv-ui-primary-hover, #f0605c);
}

.gdv-cr-form .gdv-cr-checkbox-field input[type="checkbox"]:focus-visible {
	outline: 2px solid var(--gdv-ui-focus, #8a6100);
	outline-offset: 2px;
}

/* Submit row: the shared .gdv-ui-btn, content-width and centred, with the
   mandatory-field note under it. */
.gdv-cr-form__actions {
	margin-top: 1.5rem;
	text-align: center;
}

.gdv-cr-mandatory-label {
	display: block;
	margin-top: 6px;
	font-size: 0.875rem;
	color: var(--gdv-ui-text-faint, #666666);
}

.gdv-cr-submit-info {
	margin: 0.75rem 0 0;
	font-size: 0.875rem;
	color: var(--gdv-ui-text-faint, #666666);
	text-align: center;
	line-height: 1.4;
}

/* Form-level error and the success block that replaces the form */

.gdv-cr-form__error {
	padding: 1rem 1.25rem;
	margin-bottom: 1.5rem;
	border-radius: 4px;
	border-left: 4px solid var(--gdv-ui-danger, #b32d2e);
	background: var(--gdv-cr-danger-light);
	color: var(--gdv-ui-text, #444444);
	font-size: 1rem;
	line-height: 1.6;
}

.gdv-cr-form__error[hidden],
.gdv-cr-form__success[hidden] {
	display: none;
}

.gdv-cr-form__success {
	display: flex;
	align-items: center;
	gap: 1.25rem;
	padding: 1.5rem 1.75rem;
	background: var(--gdv-cr-success-light);
	border-radius: 6px;
	border-left: 4px solid var(--gdv-ui-success, #427a7b);
}
