/*
 * SD Reviews — front end.
 *
 * Layering, resolved by source order alone:
 *   .sd-reviews          defaults
 *   .sd-preset--*        colour presets
 *   .sd-tpl--*           client templates
 *   style="--sd-…"       block controls (inline, always wins)
 *
 * Rules inside the block are written as ".sd-reviews .sd-thing" rather than
 * ".sd-thing" on its own. Not for the cascade above — that resolves on source
 * order — but for the cascade the block lands in. WordPress prefixes a theme's
 * editor CSS with .editor-styles-wrapper, so a theme rule as ordinary as
 * "article { background-color: #fff }" arrives at (0,1,1) and beats a
 * single-class rule of ours. The card is an <article>, the quote is a
 * <blockquote>, the name is a <cite>, the track is an <ol>: every part of this
 * block is an element some theme styles by tag. One extra class puts the whole
 * component above that without reaching for !important.
 *
 * There is no !important in this file, and there should never be.
 */

.sd-reviews {
	--sd-star-color: #D4621A;
	--sd-star-size: 1.05rem;
	--sd-card-bg: #1E2E3D;
	--sd-card-fg: #C5CFD8;
	--sd-card-heading: #FFFFFF;
	--sd-card-meta: #7A9AB0;
	/* The "read full review" link. Follows the card's own heading colour
	   rather than the stars, so it never comes out gold on a white card. */
	--sd-more-color: var(--sd-card-heading);
	--sd-card-border: 1px solid rgba(255, 255, 255, .07);
	--sd-card-accent: var(--sd-card-border);
	--sd-rule: rgba(255, 255, 255, .07);
	--sd-card-padding: 1.6rem;
	/* The rule beside the quote. Owned here rather than inherited from
	   whatever the theme does to a <blockquote>. */
	--sd-quote-bar: 3px solid var(--sd-quote-bar-color);
	--sd-quote-bar-color: rgba(255, 255, 255, .16);
	--sd-quote-bar-gap: 1.1rem;
	--sd-card-radius: 5px;
	--sd-card-gap: 1.25rem;
	--sd-card-min: 19rem;
	--sd-columns: 3;
	--sd-quote-color: rgba(212, 98, 26, .30);
	--sd-quote-size: 0;
	/*
	 * Controls take their colours from the card palette rather than carrying
	 * a palette of their own. That is what makes them follow the design theme:
	 * every theme sets the card colours, so the control bar changes with it,
	 * and it stays legible whatever the colour of the page behind the block —
	 * which fixed arrows and dots that were white-on-white outside the cards.
	 */
	--sd-control-size: 2.25rem;
	--sd-control-bg: var(--sd-card-bg);
	--sd-control-fg: var(--sd-card-heading);
	--sd-control-border: var(--sd-card-border);
	--sd-dot-size: .45rem;
	--sd-dot-idle: color-mix(in srgb, var(--sd-card-heading) 30%, transparent);
	/*
	 * Side arrows default to the inverse of the card, which is what keeps them
	 * visible sitting on top of one. Both halves are overridable, so a block
	 * can pick its own circle and chevron, or drop the circle entirely.
	 */
	--sd-arrow-bg: color-mix(in srgb, var(--sd-card-heading) 94%, transparent);
	--sd-arrow-fg: var(--sd-card-bg);
	--sd-arrow-shadow: 0 8px 24px rgba(9, 14, 20, .3);
	/*
	 * How wide a band the side arrows are allowed to sit at the edges of. On a
	 * full-width block the stage is the whole viewport, which stranded them
	 * against the browser edge with half a screen between them and the review.
	 * They are pulled in to this band instead; on a block narrower than it the
	 * clamp below yields 0 and nothing moves.
	 */
	--sd-controls-max: 76rem;
	/*
	 * How wide the reviews themselves are allowed to get. A full-width block
	 * is meant to let its background run edge to edge, not its text: a review
	 * stretched across a 1900px screen is a single unreadable line. The
	 * background still spans the block; only the content is held in. Set it to
	 * "none" for a deliberately full-bleed row of cards.
	 */
	--sd-content-max: 76rem;
	/*
	 * Alignment, as four tokens rather than one text-align. Centring a review
	 * is not just centring its text: the stars, the photo and the author row
	 * are flex children that have to follow, and the author row wants to stack
	 * rather than sit side by side. Themes, layouts and the block control all
	 * set the same four, so they can never half-apply.
	 */
	--sd-align-text: left;
	--sd-align-items: stretch;
	--sd-align-inline: flex-start;
	--sd-meta-direction: row;
	--sd-clamp: 6;
	--sd-transition: 280ms;
	/*
	 * The build this stylesheet came from, readable from script. The block's
	 * markup already carries its own version, but the editor re-renders that
	 * from the server on every keystroke while the stylesheet is whatever the
	 * browser cached — so the two can disagree, and when they do the editor
	 * shows a design that no longer exists. Comparing them is the only way to
	 * see it from inside.
	 */
	--sd-css-version: "1.7.0";

	container-type: inline-size;

	/*
	 * The block's own frame is written as an inline style by the renderer, not
	 * declared here. See SD_Reviews_Template::css_vars(): a stylesheet rule
	 * lost to the theme inside the editor, where WordPress prefixes theme CSS
	 * with .editor-styles-wrapper and hands it specificity this file cannot
	 * match without !important. Only the background is reset here, because
	 * nothing has been seen fighting over it.
	 */
	background-color: transparent;
}

.sd-reviews *,
.sd-reviews *::before,
.sd-reviews *::after { box-sizing: border-box; }

.sd-reviews .sd-reviews__sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.sd-reviews .sd-reviews__heading {
	font-size: clamp(1.35rem, 3.2cqi + .8rem, 1.9rem);
	line-height: 1.15;
	color: var(--sd-card-heading);
	margin: 0 0 1.4rem;
	text-wrap: balance;
}

/*
 * Everything that holds content is centred inside the block and capped. The
 * slider's track is excluded because it is the scrolling flex row — its stage
 * is capped instead, one level up, so the cards still snap and scroll.
 */
.sd-reviews .sd-reviews__heading,
.sd-reviews .sd-reviews__footer,
.sd-reviews .sd-reviews__stage,
.sd-reviews:not([data-layout="slider"]) .sd-reviews__track {
	max-width: var(--sd-content-max);
	margin-inline: auto;
}

/* ---------- the card, identical in every layout ---------- */

.sd-reviews .sd-review {
	background: var(--sd-card-bg);
	color: var(--sd-card-fg);
	border: var(--sd-card-border);
	border-left: var(--sd-card-accent);
	border-radius: var(--sd-card-radius);
	padding: var(--sd-card-padding);
	height: 100%;
	display: flex;
	flex-direction: column;
	align-items: var(--sd-align-items);
	text-align: var(--sd-align-text);
	gap: .85rem;
	margin: 0;
	position: relative;
}

.sd-reviews .sd-review__quote {
	font-family: Georgia, "Times New Roman", serif;
	font-size: var(--sd-quote-size);
	line-height: .8;
	color: var(--sd-quote-color);
	display: block;
	height: calc(var(--sd-quote-size) * .62);
	overflow: hidden;
}

.sd-reviews .sd-review__rating { display: flex; gap: .16rem; align-items: center; justify-content: var(--sd-align-inline); }

.sd-reviews .sd-review__rating svg {
	width: var(--sd-star-size);
	height: var(--sd-star-size);
	fill: var(--sd-star-color);
	flex: none;
}

.sd-reviews .sd-review__title { font-size: 1.05rem; margin: 0; color: var(--sd-card-heading); }

/*
 * The body is a <blockquote>, and every theme styles blockquotes: a left rule,
 * an indent, italics, a pull-quote font. Whatever the theme does landed on our
 * cards uninvited — and since themes style blockquotes differently inside the
 * editor than on the front, the same block looked like two different designs
 * depending on where you were standing. So it is reset to nothing here, and
 * the left rule is put back as something the block owns and can control.
 */
.sd-reviews .sd-review__body {
	margin: 0;
	padding: 0;
	border: 0;
	quotes: none;
	font-size: 1rem;
	font-style: normal;
	font-weight: 400;
	line-height: 1.62;
	text-align: inherit;
	flex: 1 1 auto;
	/*
	 * Two ends rather than one, so the rule can move to whichever side the
	 * text is hugging. Right-aligned text with the rule still pinned to the
	 * left edge leaves the two at opposite ends of the card.
	 */
	border-inline-start: var(--sd-quote-bar-lead, var(--sd-quote-bar, 0));
	border-inline-end: var(--sd-quote-bar-trail, 0);
	padding-inline-start: var(--sd-quote-bar-gap-lead, var(--sd-quote-bar-gap, 0));
	padding-inline-end: var(--sd-quote-bar-gap-trail, 0);
}

.sd-reviews .sd-review__body::before,
.sd-reviews .sd-review__body::after { content: none; }

/* The theme sizes <p> too; the quote decides its own type. */
.sd-reviews .sd-review__body p { margin: 0 0 .7em; font-size: inherit; line-height: inherit; }
.sd-reviews .sd-review__body p:last-child { margin-bottom: 0; }
.sd-reviews .sd-review__body :is(cite, footer) { font-style: normal; }

/*
 * Trimming is visual and nothing else. The review in the page is always the
 * whole review; this hides the overflow so cards that sit next to each other
 * come out the same height, and the rest is one click away — see
 * .sd-review__more and the dialog at the end of this file. Cutting the words
 * out server-side, which this block used to do, meant the visitor read a
 * shortened quote with a real person's name under it.
 *
 * Keyed to a class rather than to the layout, because a list or a single quote
 * can opt in now and neither of those is a data-layout this rule could name.
 */
.sd-reviews--clamped .sd-review__body {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: var(--sd-clamp);
	line-clamp: var(--sd-clamp);
	overflow: hidden;
	flex: 0 1 auto;
}

.sd-reviews .sd-review__more {
	align-self: var(--sd-align-inline);
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
	font: inherit;
	font-size: .85rem;
	font-weight: 600;
	color: var(--sd-more-color);
	text-decoration: underline;
	text-underline-offset: .22em;
	text-decoration-thickness: 1px;
}

.sd-reviews .sd-review__more:hover { text-decoration-thickness: 2px; }

/*
 * The link's slot is reserved in every trimmed card, needed or not, so the
 * quote and the author row keep the same rhythm across a row. Without it a
 * card with a link had it jammed against the quote while its neighbours had a
 * hole where it would have been.
 *
 * Reserved in CSS rather than by the view script, so the editor — which never
 * runs that script — spaces the cards exactly as the page does.
 */
.sd-reviews[data-layout="grid"] .sd-review__more[hidden],
.sd-reviews[data-layout="slider"] .sd-review__more[hidden] {
	display: block;
	visibility: hidden;
}

/* Pushes the author row to the bottom so trimmed and untrimmed cards align. */
.sd-reviews[data-layout="grid"] .sd-review__meta,
.sd-reviews[data-layout="slider"] .sd-review__meta { margin-top: auto; }

.sd-reviews .sd-review__reply {
	font-size: .9rem;
	color: var(--sd-card-meta);
	line-height: 1.55;
	border-left: 2px solid var(--sd-star-color);
	padding-left: .85rem;
}

.sd-reviews .sd-review__reply b {
	display: block;
	color: var(--sd-card-heading);
	font-size: .78rem;
	font-weight: 600;
	letter-spacing: .09em;
	text-transform: uppercase;
	margin-bottom: .25rem;
}

.sd-reviews .sd-review__meta {
	display: flex;
	align-items: center;
	gap: .7rem;
	flex-wrap: wrap;
	flex-direction: var(--sd-meta-direction);
	justify-content: var(--sd-align-inline);
	padding-top: .85rem;
	/* Owned, because <footer> is a tag themes give a background and a rule of
	   their own and this one has to keep taking the card's. */
	background: none;
	border-top: 1px solid var(--sd-rule);
}

.sd-reviews .sd-review__avatar {
	width: 38px;
	height: 38px;
	flex: none;
	border-radius: 50%;
	object-fit: cover;
	background: var(--sd-control-bg);
	color: var(--sd-card-heading);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: .9rem;
	font-weight: 700;
	letter-spacing: .02em;
}

.sd-reviews .sd-review__who { display: flex; flex-direction: column; align-items: var(--sd-align-inline); min-width: 0; flex: 1 1 auto; }
.sd-reviews .sd-review__author { font-style: normal; font-weight: 600; font-size: .95rem; color: var(--sd-card-heading); }

.sd-reviews .sd-review__sub {
	font-size: .78rem;
	color: var(--sd-card-meta);
	display: flex;
	gap: .45rem;
	align-items: center;
	justify-content: var(--sd-align-inline);
	flex-wrap: wrap;
}

/* <time> is styled by tag often enough that inheriting has to be spelled out. */
.sd-reviews .sd-review__sub > * {
	color: inherit;
	font-size: inherit;
	font-style: normal;
	font-weight: inherit;
}

.sd-reviews .sd-review__sub > *::after { content: "·"; margin-left: .45rem; opacity: .5; }
.sd-reviews .sd-review__sub > *:last-child::after { content: none; }

/* ---------- layout: list, and the resting state of every layout ---------- */

.sd-reviews .sd-reviews__track {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--sd-card-gap);
}

.sd-reviews .sd-reviews__item { min-width: 0; }

/* ---------- layout: grid ---------- */

.sd-reviews[data-layout="grid"] .sd-reviews__track {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(var(--sd-card-min), 1fr));
}

@container (min-width: 40rem) {
	.sd-reviews[data-layout="grid"] .sd-reviews__track {
		grid-template-columns: repeat(
			auto-fill,
			minmax(max(var(--sd-card-min), calc((100% - (var(--sd-columns) - 1) * var(--sd-card-gap)) / var(--sd-columns))), 1fr)
		);
	}
}

/* ---------- layout: single ---------- */

.sd-reviews[data-layout="single"] {
	--sd-card-padding: 2.4rem;
	--sd-quote-bar: 0;
	--sd-quote-bar-gap: 0;
	--sd-align-text: center;
	--sd-align-items: center;
	--sd-align-inline: center;
	--sd-meta-direction: column;
}
.sd-reviews[data-layout="single"] .sd-reviews__track { max-width: 44rem; margin-inline: auto; }
.sd-reviews[data-layout="single"] .sd-review { --sd-align-text: center; }
.sd-reviews[data-layout="single"] .sd-review__body { font-size: 1.22rem; line-height: 1.55; }
.sd-reviews[data-layout="single"] .sd-review__meta { border-top: 0; padding-top: .35rem; }
.sd-reviews[data-layout="single"] .sd-review__who { flex: 0 1 auto; }

/*
 * ---------- layout: slider ----------
 * Gated on [data-enhanced], which the view script adds. Until then the block
 * is a plain list: if the script never runs, every review is still readable
 * rather than one review behind two dead arrows.
 */

.sd-reviews[data-layout="slider"]:is([data-enhanced], .sd-reviews--editor) .sd-reviews__viewport {
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	scrollbar-width: none;
	margin-inline: calc(var(--sd-card-gap) * -.5);
	padding: 2px calc(var(--sd-card-gap) * .5);
	/* Matches the padding, so a snapped card lands flush with the block's
	   content edge rather than under its own gutter. */
	scroll-padding-inline: calc(var(--sd-card-gap) * .5);
}

.sd-reviews[data-layout="slider"]:is([data-enhanced], .sd-reviews--editor) .sd-reviews__viewport::-webkit-scrollbar { display: none; }
.sd-reviews[data-layout="slider"]:is([data-enhanced], .sd-reviews--editor) .sd-reviews__track { flex-direction: row; }

.sd-reviews[data-layout="slider"]:is([data-enhanced], .sd-reviews--editor) .sd-reviews__item {
	/* start, not center: the leading card is the one the arrows and dots
	   count, and centring made a three-across slider report it was on card 2
	   before anything had been pressed. */
	scroll-snap-align: start;
	flex: 0 0 clamp(17rem, 88cqi, 26rem);
}

@container (min-width: 40rem) {
	.sd-reviews[data-layout="slider"]:is([data-enhanced], .sd-reviews--editor) .sd-reviews__item { flex-basis: min(26rem, 46cqi); }
}

/* ---------- controls ---------- */

/*
 * One pill holding previous, dots and next, centred under the slider. The
 * arrows used to be pushed to the far edges by a stretched dot list, which
 * left them stranded in whitespace and reading as page furniture rather than
 * part of the block. Grouped and filled, they are legible on any background
 * and look deliberate at every width.
 */
.sd-reviews .sd-reviews__footer { margin-top: 1.6rem; display: flex; flex-direction: column; gap: .95rem; }
.sd-reviews .sd-reviews__footer--centred { align-items: center; }

.sd-reviews .sd-reviews__controls {
	display: none;
	align-items: center;
	gap: .35rem;
	padding: .3rem;
	background: var(--sd-control-bg);
	border: var(--sd-control-border);
	border-radius: 999px;
}

.sd-reviews:is([data-enhanced], .sd-reviews--editor) .sd-reviews__controls { display: inline-flex; }
.sd-reviews .sd-reviews__controls[data-controls="dots"] .sd-reviews__arrow { display: none; }
.sd-reviews .sd-reviews__controls[data-controls="arrows"] .sd-reviews__dots { display: none; }
.sd-reviews .sd-reviews__controls[data-controls="edge"] .sd-reviews__dots { display: none; }

.sd-reviews .sd-reviews__arrow {
	width: var(--sd-control-size);
	height: var(--sd-control-size);
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	cursor: pointer;
	background: transparent;
	color: var(--sd-control-fg);
	border: 0;
	border-radius: 50%;
	transition: background var(--sd-transition), color var(--sd-transition);
}

.sd-reviews .sd-reviews__arrow:hover:not(:disabled) {
	background: var(--sd-star-color);
	color: #fff;
}

.sd-reviews .sd-reviews__arrow:disabled { opacity: .3; cursor: default; }

.sd-reviews .sd-reviews__arrow svg {
	width: 1rem;
	height: 1rem;
	fill: none;
	stroke: currentColor;
	stroke-width: 2.2;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.sd-reviews .sd-reviews__dots {
	list-style: none;
	display: flex;
	align-items: center;
	gap: .45rem;
	margin: 0;
	padding: 0 .5rem;
	flex: 0 1 auto;
}

.sd-reviews .sd-reviews__dots button {
	width: var(--sd-dot-size);
	height: var(--sd-dot-size);
	padding: 0;
	border: 0;
	border-radius: 50%;
	cursor: pointer;
	background: var(--sd-dot-idle);
	transition: background var(--sd-transition), transform var(--sd-transition);
}

.sd-reviews .sd-reviews__dots button[aria-current="true"] { background: var(--sd-star-color); transform: scale(1.4); }

/*
 * Past about ten reviews a dot per review becomes a stripe, so the list
 * scrolls inside the pill instead of stretching it across the block.
 */
.sd-reviews .sd-reviews__dots--many {
	max-width: min(14rem, 45cqi);
	overflow-x: auto;
	scrollbar-width: none;
}

.sd-reviews .sd-reviews__dots--many::-webkit-scrollbar { display: none; }

/* ---------- edge arrows ---------- */

/*
 * The stage exists only to give the floating arrows something to be centred
 * against: the viewport is a scroll container, so anything positioned inside
 * it would scroll away with the cards.
 */
.sd-reviews .sd-reviews__stage { position: relative; }

.sd-reviews .sd-reviews__arrow--edge {
	display: none;
	position: absolute;
	top: 50%;
	translate: 0 -50%;
	z-index: 2;
	width: 2.85rem;
	height: 2.85rem;
	border-radius: 50%;
	border: 0;
	/*
	 * Inverted against the card rather than matched to it. These sit ON the
	 * cards, so a control-coloured circle on a control-coloured card is a
	 * circle you cannot see — which is exactly what the pill colours produced
	 * here. Taking the fill from the heading colour and the chevron from the
	 * card guarantees contrast in every theme, light or dark.
	 */
	color: var(--sd-arrow-fg);
	background: var(--sd-arrow-bg);
	box-shadow: var(--sd-arrow-shadow);
	transition: background var(--sd-transition), color var(--sd-transition), scale var(--sd-transition);
}

.sd-reviews .sd-reviews__arrow--edge:hover:not(:disabled) {
	background: var(--sd-star-color);
	color: #fff;
}

/* The card is transparent in this theme, so the chevron takes the page's own
   background instead of the card's. */
/*
 * Classic — the original 1.x look, rebuilt.
 *
 * No card at all: centred black text on whatever the page provides, gold
 * stars, and the reviewer's name above them. The order is the only structural
 * difference in the whole stylesheet, and it needs no separate markup because
 * the card is already a flex column — the rating is simply sent past the
 * author row. Anything that would draw a box (background, border, padding,
 * the rule above the author row) is zeroed rather than restyled.
 */
.sd-preset--classic {
	/* Centred text has no left edge to hang a rule from. */
	--sd-quote-bar: 0;
	--sd-quote-bar-gap: 0;
	--sd-quote-bar-color: #1A1A1A;
	/* The quote itself is capped at 46rem and centred, so the arrows sit just
	   outside it rather than out at the block's own edges. */
	--sd-controls-max: 58rem;
	--sd-star-color: #F5C518;
	--sd-star-size: 1.4rem;
	--sd-card-bg: transparent;
	--sd-card-fg: #1A1A1A;
	--sd-card-heading: #000000;
	--sd-card-meta: #565656;
	--sd-card-border: 0;
	--sd-card-accent: 0;
	--sd-rule: transparent;
	--sd-card-padding: 0;
	--sd-card-radius: 0;
	--sd-card-gap: 2.9rem;
	--sd-quote-color: rgba(0, 0, 0, .12);
	--sd-arrow-bg: transparent;
	--sd-arrow-fg: var(--sd-card-heading);
	--sd-arrow-shadow: none;
	--sd-dot-idle: rgba(0, 0, 0, .22);
}

.sd-preset--classic {
	--sd-align-text: center;
	--sd-align-items: center;
	--sd-align-inline: center;
	--sd-meta-direction: column;
}

.sd-preset--classic .sd-review {
	justify-content: center;
	gap: 1rem;
}

/*
 * Quote, name and stars stay together as one group. Everywhere else the author
 * row is pinned to the bottom of the card so cards line up; here there is no
 * card, so pinning it just opened a gap under the quote.
 */
.sd-preset--classic .sd-review__body { flex: 0 1 auto; }
.sd-reviews.sd-preset--classic .sd-review__meta { margin-top: 0; }

/*
 * Except in a grid, where the reviews do stand side by side. Quotes are never
 * the same length, so a centred group left every name and every row of stars
 * at a different height across the row. Pinned to the bottom they share a
 * baseline, and because the stars come after the name in this theme, both
 * travel down together.
 */
.sd-reviews.sd-preset--classic[data-layout="grid"] .sd-review { justify-content: flex-start; }
.sd-reviews.sd-preset--classic[data-layout="grid"] .sd-review__meta { margin-top: auto; }

/*
 * And left-aligned. Centred text reads fine as one wide quote, but stacked in
 * a narrow grid column every line starts in a different place and the eye has
 * nothing to come back to. The block control overrides this either way.
 */
.sd-reviews.sd-preset--classic[data-layout="grid"] {
	--sd-align-text: left;
	--sd-align-items: stretch;
	--sd-align-inline: flex-start;
	--sd-meta-direction: row;
}

.sd-preset--classic .sd-review__body { max-width: 46rem; }

/*
 * Author row second, stars last. Stacked when centred — with the photo beside
 * the name the pair centres as a unit, which leaves the name itself off the
 * axis the quote above it is centred on — and side by side when it is not,
 * which the direction token handles for both cases.
 */
.sd-preset--classic .sd-review__meta {
	order: 2;
	border-top: 0;
	padding-top: 0;
	gap: .5rem;
}

.sd-preset--classic .sd-review__rating { order: 3; }

.sd-preset--classic .sd-review__who { flex: 0 1 auto; }

/* The initials fallback takes its fill from the control colour, which this
   theme makes transparent — so it gets its own, or it reads as loose text. */
.sd-preset--classic .sd-review__avatar {
	background: rgba(0, 0, 0, .07);
	color: var(--sd-card-heading);
}

.sd-preset--classic .sd-review__author {
	font-size: 1.4rem;
	font-weight: 700;
	line-height: 1.2;
}


.sd-preset--classic .sd-reviews__heading { text-align: center; }

/*
 * One review at a time. Classic has no card to sit beside another card, so a
 * three-across slider reads as three loose columns of text rather than one
 * quote; the original design showed a single testimonial per slide and this
 * keeps that.
 */
.sd-reviews.sd-preset--classic[data-layout="slider"]:is([data-enhanced], .sd-reviews--editor) .sd-reviews__item {
	flex-basis: 100%;
}

.sd-preset--classic .sd-reviews__viewport { padding-inline: clamp(2.5rem, 7cqi, 5rem); }
.sd-preset--classic .sd-review__body { margin-inline: auto; }

/* The control pill would be a box on a design that has none of them. */
.sd-preset--classic .sd-reviews__controls {
	background: transparent;
	border: 0;
}

.sd-preset--inherit {
	--sd-arrow-bg: color-mix(in srgb, currentColor 90%, transparent);
	--sd-arrow-fg: Canvas;
}


.sd-reviews .sd-reviews__arrow--edge:hover:not(:disabled) { scale: 1.06; }
/* max() keeps the arrows at the stage edge whenever the stage is already
   narrower than the band, so only wide and full-width blocks are affected. */
.sd-reviews .sd-reviews__arrow--edge.sd-reviews__arrow--prev {
	left: max(.65rem, calc(50% - var(--sd-controls-max) / 2));
}

.sd-reviews .sd-reviews__arrow--edge.sd-reviews__arrow--next {
	right: max(.65rem, calc(50% - var(--sd-controls-max) / 2));
}

/* Dots only in the pill: the arrows for this mode are on the slider. */
.sd-reviews .sd-reviews__controls[data-controls="edgedots"] .sd-reviews__arrow { display: none; }

/*
 * Wide enough for a floating arrow not to cover the text it sits on: the
 * arrows come out onto the slider, and the arrows-only pill steps aside. Below
 * this the pill is the control, which is why it is always rendered.
 */
@container (min-width: 30rem) {
	.sd-reviews:is([data-enhanced], .sd-reviews--editor) .sd-reviews__arrow--edge { display: flex; }
	.sd-reviews:is([data-enhanced], .sd-reviews--editor) .sd-reviews__controls[data-controls="edge"] { display: none; }
}


.sd-reviews :is(button, a):focus-visible { outline: 2px solid var(--sd-star-color); outline-offset: 3px; }

.sd-reviews .sd-reviews__attribution {
	font-size: .75rem;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--sd-card-meta);
	margin: 0;
}

.sd-reviews--empty {
	border: 1px dashed var(--sd-card-meta);
	border-radius: var(--sd-card-radius);
	padding: 1rem 1.25rem;
	color: var(--sd-card-meta);
	font-size: .9rem;
}

@media (prefers-reduced-motion: reduce) {
	.sd-reviews .sd-reviews__viewport { scroll-behavior: auto; }
	.sd-reviews * { transition-duration: 1ms; }
}

/* ============================================================
   PRESETS
   ============================================================ */

.sd-preset--light {
	--sd-quote-bar-color: #DDE6ED;
	--sd-star-color: #D4621A;
	--sd-card-bg: #FFFFFF;
	--sd-card-fg: #33414D;
	--sd-card-heading: #0F1923;
	--sd-card-meta: #5C7386;
	--sd-card-border: 1px solid #DDE6ED;
	--sd-card-accent: var(--sd-card-border);
	--sd-rule: #E6EDF2;
	--sd-quote-color: rgba(212, 98, 26, .22);
}

.sd-preset--whitegold {
	--sd-quote-bar-color: #1A1A1A;
	--sd-star-color: #E0A11B;
	--sd-card-bg: #FFFFFF;
	--sd-card-fg: #1A1A1A;
	--sd-card-heading: #000000;
	--sd-card-meta: #6B6B6B;
	--sd-card-border: 1px solid #E4E4E4;
	--sd-card-accent: var(--sd-card-border);
	--sd-rule: #ECECEC;
	--sd-card-radius: 4px;
	--sd-quote-color: #E4E4E4;
}

.sd-preset--inherit {
	--sd-star-color: currentColor;
	--sd-card-bg: transparent;
	--sd-card-fg: inherit;
	--sd-card-heading: inherit;
	--sd-card-meta: inherit;
	--sd-card-border: 1px solid color-mix(in srgb, currentColor 16%, transparent);
	--sd-card-accent: var(--sd-card-border);
	--sd-rule: color-mix(in srgb, currentColor 14%, transparent);
	--sd-quote-color: color-mix(in srgb, currentColor 22%, transparent);
	--sd-quote-bar-color: color-mix(in srgb, currentColor 20%, transparent);
	/* The card is transparent in this theme, so the control pill cannot take
	   its fill from it and keeps a tint of the surrounding text colour. */
	--sd-control-bg: color-mix(in srgb, currentColor 8%, transparent);
	--sd-control-fg: inherit;
	--sd-control-border: 1px solid color-mix(in srgb, currentColor 18%, transparent);
	--sd-dot-idle: color-mix(in srgb, currentColor 28%, transparent);
}

.sd-preset--inherit .sd-review__body,
.sd-preset--inherit .sd-review__author,
.sd-preset--inherit .sd-review__sub { color: inherit; }


/* ---------- block background ---------- */

/*
 * An image behind the whole block, with a tint over it so review text stays
 * readable whatever the photo is doing. The tint is a pseudo-element rather
 * than a second background layer so its strength can be changed without
 * touching the image, and the block's own children are lifted above it.
 */
.sd-reviews--bg {
	position: relative;
	background-image: var(--sd-bg-image);
	background-size: cover;
	background-position: var(--sd-bg-position, center center);
	background-repeat: no-repeat;
	isolation: isolate;
}

.sd-reviews--bg::before {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--sd-bg-overlay, #0F1923);
	opacity: var(--sd-bg-overlay-opacity, .45);
	z-index: 0;
	pointer-events: none;
	border-radius: inherit;
}

.sd-reviews--bg > * { position: relative; z-index: 1; }

/* ---------- bare chevrons ---------- */

/*
 * With the circle gone the arrow is no longer a button sitting on a card, so
 * it moves out to the block's own edge and grows. Anything smaller reads as a
 * stray character rather than a control.
 */
.sd-reviews--bare-arrows .sd-reviews__arrow--edge {
	width: 2.4rem;
	height: 3.4rem;
	border-radius: 0;
	opacity: .75;
	transition: opacity var(--sd-transition), scale var(--sd-transition);
}

.sd-reviews--bare-arrows .sd-reviews__arrow--edge:hover:not(:disabled) {
	background: transparent;
	color: var(--sd-arrow-fg);
	opacity: 1;
	scale: 1.12;
}

.sd-reviews--bare-arrows .sd-reviews__arrow--edge svg {
	width: 1.6rem;
	height: 1.6rem;
	stroke-width: 1.4;
}

.sd-reviews--bare-arrows .sd-reviews__arrow--edge.sd-reviews__arrow--prev {
	left: max(0px, calc(50% - var(--sd-controls-max) / 2));
}

.sd-reviews--bare-arrows .sd-reviews__arrow--edge.sd-reviews__arrow--next {
	right: max(0px, calc(50% - var(--sd-controls-max) / 2));
}

/* ---------- full review dialog ---------- */

.sd-reviews .sd-reviews__modal {
	width: min(38rem, calc(100vw - 2.5rem));
	max-height: min(80vh, 44rem);
	padding: 0;
	border: var(--sd-card-border);
	border-radius: var(--sd-card-radius);
	background: var(--sd-card-bg);
	color: var(--sd-card-fg);
	overflow: visible;
	box-shadow: 0 24px 60px rgba(9, 14, 20, .35);
}

.sd-reviews .sd-reviews__modal[open] { animation: sd-reviews-pop 180ms ease-out; }

@keyframes sd-reviews-pop {
	from { opacity: 0; transform: translateY(6px) scale(.985); }
	to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
	.sd-reviews .sd-reviews__modal[open] { animation: none; }
}

/* The dialog is not inside the block's stacking context once open, so the
   theme's custom properties are re-declared on it by the view script. */
.sd-reviews .sd-reviews__modal::backdrop { background: rgba(9, 14, 20, .62); }

.sd-reviews .sd-reviews__modal-body {
	padding: clamp(1.4rem, 4cqi, 2.2rem);
	max-height: min(80vh, 44rem);
	overflow-y: auto;
}

/* Inside the dialog the card is the dialog: no second border, no clamp. */
.sd-reviews .sd-reviews__modal .sd-review {
	background: none;
	border: 0;
	border-radius: 0;
	padding: 0;
	height: auto;
}

.sd-reviews .sd-reviews__modal .sd-review__body {
	display: block;
	overflow: visible;
	-webkit-line-clamp: none;
	line-clamp: none;
}

.sd-reviews .sd-reviews__modal .sd-review__more { display: none; }

.sd-reviews .sd-reviews__modal-close {
	position: absolute;
	top: .55rem;
	right: .55rem;
	width: 2.1rem;
	height: 2.1rem;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	cursor: pointer;
	background: none;
	border: 0;
	border-radius: 50%;
	color: var(--sd-card-meta);
	transition: background var(--sd-transition), color var(--sd-transition);
}

.sd-reviews .sd-reviews__modal-close:hover { background: var(--sd-star-color); color: #fff; }

.sd-reviews .sd-reviews__modal-close svg {
	width: 1.05rem;
	height: 1.05rem;
	fill: none;
	stroke: currentColor;
	stroke-width: 2.2;
	stroke-linecap: round;
}


/* ---------- editor preview ---------- */

/*
 * The preview is rendered through REST and the view script never runs there,
 * so anything that script builds is absent. An empty dot list would otherwise
 * render as a stray pill, and the viewport would scroll where the published
 * page snaps. "Read full review" stays hidden here exactly as it starts on the
 * page, because whether a card overflowed is a question only the browser can
 * answer and forcing it visible would invent a difference rather than remove
 * one.
 */
.sd-reviews--editor .sd-reviews__dots:empty { display: none; }
.sd-reviews--editor .sd-reviews__controls:not(:has(.sd-reviews__arrow)) { display: none; }
.sd-reviews--editor .sd-reviews__viewport { overflow-x: hidden; }
