/**
 * Librarian — review-page layout.
 *
 * Scoped under .lbr-rvp (and .lbr-rvp-wrap for the classic-template
 * shell). Card styling mirrors the app grid: cover, serif title,
 * muted "Reviewer · year" meta.
 */

.lbr-rvp {
	--rvp-serif: 'Lora', Georgia, serif;
	--rvp-sans: 'Open Sans', Arial, sans-serif;
	--rvp-ink: #1f2937;
	--rvp-muted: #6b7280;
	--rvp-accent: #283B91;
	--rvp-border: #e5e7eb;
	max-width: 1080px;
	margin: 0 auto;
	padding: 32px 20px 64px;
	font-family: var(--rvp-sans);
	color: var(--rvp-ink);
}

/* — Head — */

/* Category as the app's section-label eyebrow — small caps between
   hairlines. The back-to-search pill stays the page's only pill, so
   action (pill) and classification (eyebrow) never read as siblings. */
.lbr-rvp-cats {
	display: flex;
	align-items: center;
	gap: 16px;
	margin: 0 0 20px;
}

.lbr-rvp-cats::before,
.lbr-rvp-cats::after {
	content: '';
	flex: 1;
	border-top: 1px solid var(--rvp-border);
}

.lbr-rvp-cat {
	display: inline-block;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	text-decoration: none;
	color: var(--rvp-muted);
}

.lbr-rvp-cat + .lbr-rvp-cat::before {
	content: '·';
	margin-right: 14px;
	opacity: 0.4;
}

.lbr-rvp-cat:hover {
	color: var(--rvp-accent);
}

/* The head freezes AS IS — full size, no morph — and the review
   scrolls beneath it. Constant height means nothing below can ever
   move. The side column's top offset is set by JS to clear it. */
.lbr-rvp-head {
	position: sticky;
	/* Pinned flush to the nav, with the 16px of breathing room carried
	   INSIDE as opaque padding — an external gap was a transparent
	   window the scrolling text showed through. The background is the
	   PAGE's own colour (detected at runtime — themes run off-white),
	   so the pinned block has no visible card edges; scrolling text
	   dissolves into the gradient below instead of hitting a line. */
	top: 80px;
	z-index: 20;
	background: var(--rvp-bg, #fff);
	padding-top: 28px;
	padding-bottom: 10px;
}

.lbr-rvp-head::after {
	content: '';
	position: absolute;
	/* Only over the TEXT column (260px cover + 44px gap): the cover
	   pins just below the head and must never sit under the fade. */
	left: 304px;
	right: 0;
	top: 100%;
	height: 30px;
	background: linear-gradient(to bottom, var(--rvp-bg, #fff), transparent);
	pointer-events: none;
}

body.admin-bar .lbr-rvp-head {
	top: 112px;
}

.lbr-rvp-title {
	font-family: var(--rvp-serif);
	font-size: clamp(28px, 4vw, 40px);
	line-height: 1.15;
	margin: 0 0 6px;
	color: var(--rvp-ink);
}

.lbr-rvp-subtitle {
	font-family: var(--rvp-serif);
	font-size: clamp(17px, 2.2vw, 21px);
	font-style: italic;
	color: var(--rvp-muted);
	margin: 0 0 10px;
}

.lbr-rvp-byline {
	font-size: 14px;
	color: var(--rvp-muted);
	margin: 0 0 6px;
}

/* Byline separator: a small diamond with real breathing room — the
   book's author and the review's author are different facts. */
.lbr-rvp-dot {
	display: inline-block;
	font-size: 9px;
	opacity: 0.4;
	margin: 0 10px;
	vertical-align: 1px;
}

/* — Columns — */

.lbr-rvp-cols {
	display: grid;
	grid-template-columns: 260px 1fr;
	gap: 44px;
	margin-top: 28px;
}

/* The cover column keeps the reader company: median reviews (~250
   words) never scroll it away; the long quarter (800+ words) keep the
   book, its metadata and the escape routes in view while reading. */
.lbr-rvp-side {
	position: sticky;
	top: 158px;
	align-self: start;
}

body.admin-bar .lbr-rvp-side {
	top: 190px;
}

/* position:sticky dies beneath ANY overflow-clipping ancestor, and
   themes guard against stray-width elements with overflow-x:hidden on
   body and .site (BuddyBoss does both). On review pages our layout
   owns the width, so the guard costs nothing to lift. */
body.single-rcno_review {
	overflow: visible;
}

/* !important: the theme pins this with a higher-specificity selector. */
body.single-rcno_review .site {
	overflow: visible !important;
}

/* The cover's button wrapper must be invisible — themes paint bare
   buttons as big colored pills. */
.lbr-rvp .lbr-rvp-cover-btn {
	display: block;
	width: 100%;
	padding: 0;
	margin: 0;
	border: 0;
	border-radius: 0;
	background: transparent;
	box-shadow: none;
	min-height: 0;
	line-height: 0;
	cursor: zoom-in;
}

.lbr-rvp .lbr-rvp-cover-btn:hover,
.lbr-rvp .lbr-rvp-cover-btn:focus {
	background: transparent;
	box-shadow: none;
}

.lbr-rvp-cover {
	width: 100%;
	height: auto;
	border-radius: 8px;
	border: 1px solid var(--rvp-border);
	box-shadow: 0 10px 28px rgba(31, 41, 55, 0.14);
	margin-bottom: 18px;
}

.lbr-rvp-meta {
	margin: 0 0 14px;
	font-size: 13px;
	border-top: 1px solid var(--rvp-border);
}

.lbr-rvp-meta-row {
	display: flex;
	justify-content: space-between;
	gap: 12px;
	padding: 7px 2px;
	border-bottom: 1px solid var(--rvp-border);
}

.lbr-rvp-meta dt {
	color: var(--rvp-muted);
	font-weight: 400;
	margin: 0;
}

.lbr-rvp-meta dd {
	margin: 0;
	text-align: right;
	color: var(--rvp-ink);
}

.lbr-rvp-blurb {
	font-size: 13px;
	color: var(--rvp-muted);
}

.lbr-rvp-blurb summary {
	cursor: pointer;
	padding: 6px 0;
	color: var(--rvp-ink);
	font-weight: 600;
}

.lbr-rvp-blurb-text {
	line-height: 1.6;
	padding: 6px 0 2px;
}

/* A quiet text link, not a call-to-action — themes style bare buttons
   as big pills, so reset everything they might impose. */
.lbr-rvp .lbr-rvp-blurb-more {
	display: inline;
	background: transparent;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	padding: 0;
	margin: 0 0 0 4px;
	min-height: 0;
	height: auto;
	line-height: inherit;
	font-family: inherit;
	font-size: inherit;
	font-weight: 600;
	color: var(--rvp-accent);
	text-decoration: underline;
	text-underline-offset: 2px;
	cursor: pointer;
}

.lbr-rvp .lbr-rvp-blurb-more:hover {
	background: transparent;
	color: #1b2a6b;
	text-decoration: underline;
}

/* — Review text: readable serif, ragged right, never justified — */

.lbr-rvp-body {
	font-family: var(--rvp-serif);
	font-size: 17.5px;
	line-height: 1.75;
	color: var(--rvp-ink);
	text-align: left;
	min-width: 0;
}

.lbr-rvp-body p {
	margin: 0 0 1.25em;
}

/* — "Other Books Received": a listing rather than a review — */

/* The page speaking in its own voice about why there is no review, so
   it takes the sans face the chrome uses rather than the serif the
   reviews are set in. A rule down the side does the separating — a
   tinted box would read as a warning, and nothing here is wrong. */
.lbr-rvp-listing-note {
	font-family: var(--rvp-sans);
	font-size: 14px;
	line-height: 1.6;
	color: var(--rvp-muted);
	border-left: 3px solid var(--rvp-border);
	padding: 2px 0 2px 16px;
	margin: 0 0 32px;
}

/* With no review to carry the column, the publisher's description is
   the body text — so it is set like the review it stands in for,
   rather than left as the sidebar disclosure it is on a reviewed book. */
.lbr-rvp-listing-blurb {
	font-family: var(--rvp-serif);
	font-size: 17.5px;
	line-height: 1.75;
}

.lbr-rvp-listing-blurb p {
	margin: 0 0 1.25em;
}

.lbr-rvp-listing-blurb-title {
	font-family: var(--rvp-sans);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--rvp-muted);
	margin: 0 0 14px;
}

/* — Related rails — */

.lbr-rvp-related {
	position: relative;
	margin-top: 52px;
}

.lbr-rvp-related-title {
	font-family: var(--rvp-sans);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--rvp-muted);
	text-align: center;
	margin: 0 0 20px;
	display: flex;
	align-items: center;
	gap: 16px;
}

.lbr-rvp-related-title::before,
.lbr-rvp-related-title::after {
	content: '';
	flex: 1;
	border-top: 1px solid var(--rvp-border);
}

.lbr-rvp-rail {
	display: flex;
	gap: 18px;
	overflow-x: auto;
	/* A rail at its end otherwise chains the swipe to the document, and
	   the page rubber-bands sideways — the white strip down the right on
	   Android. The rail stops at its own edge. */
	overscroll-behavior-x: contain;
	scrollbar-width: none;
	cursor: grab;
	padding: 4px 2px 10px;
	-webkit-mask-image: linear-gradient(to right, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
	mask-image: linear-gradient(to right, transparent 0, #000 24px, #000 calc(100% - 24px), transparent 100%);
}

.lbr-rvp-related--at-start .lbr-rvp-rail {
	-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent 100%);
	mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent 100%);
}

.lbr-rvp-related--at-end .lbr-rvp-rail {
	-webkit-mask-image: linear-gradient(to right, transparent 0, #000 24px);
	mask-image: linear-gradient(to right, transparent 0, #000 24px);
}

.lbr-rvp-rail::-webkit-scrollbar {
	display: none;
}

.lbr-rvp-rail--dragging {
	cursor: grabbing;
	user-select: none;
}

.lbr-rvp-rail--dragging .lbr-rvp-card {
	pointer-events: none;
}

.lbr-rvp-card {
	flex: 0 0 132px;
	text-decoration: none;
	display: block;
	/* The star sits on the cover. */
	position: relative;
}

/* ── Rail card star ───────────────────────────────────────────────────
   Same drawing, same manners and the same reset armour as the browse
   grid's card stars: this theme paints background, border, radius and
   shadow onto every <button>, and without the !importants a ghost disc
   appears behind the star. */
.lbr-rvp-card-star,
.lbr-rvp-card-star:hover,
.lbr-rvp-card-star:focus,
.lbr-rvp-card-star:active {
	position: absolute;
	top: 5px;
	right: 7px;
	z-index: 3;
	appearance: none;
	-webkit-appearance: none;
	border: 0 !important;
	background: none !important;
	box-shadow: none !important;
	border-radius: 0 !important;
	outline: none;
	padding: 3px;
	line-height: 0;
	cursor: pointer;
	opacity: 0;
	transition: opacity 0.15s ease, transform 0.15s ease;
}

/* Idle it is invisible; hovering the card offers it, and once saved it
   stays lit as the record that the book is kept. Touch devices have no
   hover, so a saved star is the only one they ever see — which is why
   focus-visible is in here too, for the keyboard. */
.lbr-rvp-card:hover .lbr-rvp-card-star,
.lbr-rvp-card-star:focus-visible,
.lbr-rvp-card-star--saved {
	opacity: 1 !important;
}

.lbr-rvp-card-star:hover {
	transform: scale(1.12);
}

.lbr-rvp-card-star svg {
	width: 24px;
	height: 24px;
	display: block;
	filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.55));
}

.lbr-rvp-card-star svg path {
	fill: rgba(255, 255, 255, 0.2);
	stroke: #fff;
	stroke-width: 2;
	stroke-linejoin: round;
	stroke-linecap: round;
}

.lbr-rvp-card-star--saved svg {
	filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.3));
}

.lbr-rvp-card-star--saved svg path {
	fill: #e0a800;
	stroke: #e0a800;
}

/* Save/Remove rollover tip, left of the star so it stays on the cover. */
.lbr-rvp-card-star::after {
	content: attr(data-tip);
	position: absolute;
	right: calc(100% + 6px);
	top: 50%;
	transform: translateY(-50%);
	background: #2c3140;
	color: #fff;
	font-family: 'Open Sans', Arial, sans-serif;
	font-size: 11px;
	font-weight: 600;
	line-height: 1;
	padding: 5px 9px;
	border-radius: 4px;
	white-space: nowrap;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.12s ease;
}

@media (hover: hover) {
	.lbr-rvp-card-star:hover::after {
		opacity: 1;
	}
}

/* After a click the tip goes quiet until the pointer leaves and comes
   back — it must never flip Save→Remove live under the cursor, and a
   fade-out would flash the freshly flipped word. */
.lbr-rvp-card-star.lbr-star-quiet::after {
	opacity: 0 !important;
	transition: none;
}

/* ── Save confirmation toast ─────────────────────────────────────────
   Deliberately identical to the browse app's (assets/css/librarian.css)
   — the two pages load different stylesheets and share no variables,
   and one confirmation that moves or changes colour between them would
   read as two different things happening. */
.lbr-toast {
	position: fixed;
	left: 50%;
	bottom: 28px;
	z-index: 100000;
	display: flex;
	align-items: center;
	gap: 9px;
	max-width: calc(100vw - 32px);
	padding: 11px 18px;
	border-radius: 999px;
	background: #2c3140;
	color: #fff;
	font-family: 'Open Sans', Arial, sans-serif;
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	box-shadow: 0 6px 24px rgba(0, 0, 0, 0.28);
	transform: translate(-50%, 14px);
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.2s ease, transform 0.2s ease;
}

.lbr-toast--on {
	opacity: 1;
	transform: translate(-50%, 0);
}

.lbr-toast-tick {
	width: 17px;
	height: 17px;
	flex: 0 0 auto;
	color: #e0a800;
}

.lbr-toast-text {
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

@media (prefers-reduced-motion: reduce) {
	.lbr-toast {
		transition: opacity 0.2s ease;
		transform: translate(-50%, 0);
	}
}

.lbr-rvp-card-cover {
	display: block;
	width: 132px;
	height: 198px;
	object-fit: cover;
	background: #E2E5E8;
	border-radius: 8px;
	border: 1px solid var(--rvp-border);
	box-shadow: 0 4px 14px rgba(31, 41, 55, 0.12);
	margin-bottom: 10px;
	transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.lbr-rvp-card:hover .lbr-rvp-card-cover {
	transform: translateY(-3px);
	box-shadow: 0 10px 22px rgba(31, 41, 55, 0.18);
}

.lbr-rvp-card-cover--none {
	background: #E9EBEE;
	color: rgba(90, 90, 90, 0.85);
	font-family: var(--rvp-serif);
	font-size: 13px;
	line-height: 1.3;
	padding: 14px 10px;
	overflow: hidden;
	text-align: center;
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
}

.lbr-rvp-card-title {
	display: block;
	font-family: var(--rvp-serif);
	font-size: 14px;
	font-weight: 600;
	line-height: 1.3;
	color: var(--rvp-accent);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.lbr-rvp-card-meta {
	display: block;
	font-size: 12px;
	color: var(--rvp-muted);
	margin-top: 3px;
}

/* Skeleton placeholders: the promise of more, in calm grey. */

.lbr-rvp-skel {
	pointer-events: none;
}

.lbr-rvp-skel-cover {
	display: block;
	width: 132px;
	height: 198px;
	border-radius: 8px;
	border: 1px solid var(--rvp-border);
	background: #E2E5E8;
	margin-bottom: 10px;
	animation: lbrRvpPulse 1.8s ease-in-out infinite;
}

.lbr-rvp-skel-line {
	display: block;
	height: 14px;
	border-radius: 7px;
	background: #E9EBEE;
	margin-top: 9px;
	width: 90%;
	animation: lbrRvpPulse 1.8s ease-in-out infinite;
}

.lbr-rvp-skel-line--t2 {
	width: 68%;
	margin-top: 6px;
}

.lbr-rvp-skel-line--meta {
	height: 11px;
	width: 52%;
	margin-top: 7px;
	background: #EEF0F2;
}

@keyframes lbrRvpPulse {
	0%, 100% { opacity: 1; }
	50% { opacity: 0.55; }
}

@media (prefers-reduced-motion: reduce) {
	.lbr-rvp-skel-cover,
	.lbr-rvp-skel-line {
		animation: none;
	}
}

.lbr-rvp-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-30%);
	width: 34px;
	height: 34px;
	border-radius: 50%;
	border: 1px solid var(--rvp-border);
	background: #fff;
	color: var(--rvp-ink);
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0 0 2px;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
	transition: opacity 0.2s ease;
	z-index: 1;
}

.lbr-rvp-arrow--left {
	left: -10px;
}

.lbr-rvp-arrow--right {
	right: -10px;
}

.lbr-rvp-related--at-start .lbr-rvp-arrow--left,
.lbr-rvp-related--at-end .lbr-rvp-arrow--right {
	opacity: 0;
	pointer-events: none;
}

@media (pointer: coarse) {
	.lbr-rvp-arrow {
		display: none;
	}
}

/* — Modals: cover lightbox + full publisher's description — */

body.lbr-rvp-modal-open {
	overflow: hidden;
}

.lbr-rvp-modal {
	position: fixed;
	inset: 0;
	z-index: 100000;
	background: rgba(15, 23, 42, 0.62);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 28px;
}

.lbr-rvp-modal-box {
	position: relative;
	background: #fff;
	border-radius: 12px;
	box-shadow: 0 24px 64px rgba(0, 0, 0, 0.35);
	max-width: min(680px, 92vw);
	max-height: 86vh;
	overflow: auto;
	padding: 30px 34px;
	font-family: 'Open Sans', Arial, sans-serif;
	color: #1f2937;
}

/*
 * Drawer variant — a panel at the right, not a dialog over the page.
 *
 * Reporting a problem is a conversation ABOUT the text: "what does it
 * currently say?" is unanswerable if the form covers the thing being quoted.
 * So the overlay does not dim, does not take pointer events, and does not lock
 * the body — the article stays readable, scrollable and selectable while the
 * form is open, which is the whole point.
 */
.lbr-rvp-modal--drawer {
	background: none;
	pointer-events: none;
	display: block;
	padding: 0;
}

.lbr-rvp-modal-box--drawer {
	pointer-events: auto;
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	width: min(420px, 100vw);
	max-width: none;
	max-height: none;
	border-radius: 0;
	box-shadow: -8px 0 32px rgba(0, 0, 0, 0.18);
	overflow-y: auto;
	padding: 28px 26px 40px;
	animation: lbr-rvp-drawer-in 0.22s ease-out;
}

@keyframes lbr-rvp-drawer-in {
	from { transform: translateX(100%); }
	to   { transform: none; }
}

@media ( prefers-reduced-motion: reduce ) {
	.lbr-rvp-modal-box--drawer { animation: none; }
}

/* Narrow screens have no room beside the text, so it becomes a bottom sheet
   rather than a panel that covers everything anyway. */
@media ( max-width: 600px ) {
	.lbr-rvp-modal-box--drawer {
		top: auto;
		width: 100vw;
		max-height: 82vh;
		border-radius: 14px 14px 0 0;
		box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.22);
		animation-name: lbr-rvp-sheet-in;
	}
	@keyframes lbr-rvp-sheet-in {
		from { transform: translateY(100%); }
		to   { transform: none; }
	}
}

.lbr-rvp-modal-box--drawer h3 {
	font-family: 'Lora', Georgia, serif;
	font-size: 20px;
	margin: 0 0 14px;
	padding-right: 34px;
}

/*
 * With the drawer open the page moves aside instead of being covered. The
 * drawer is fixed, so the gap it slides into has to be made by the document —
 * a panel hiding the right-hand third of an article is barely better than a
 * modal when the form exists to describe that article.
 *
 * padding-right rather than a transform: transforms create a containing block
 * and would break any position:fixed header the theme owns.
 */
html.lbr-rvp-drawer-open body {
	padding-right: min(420px, 100vw);
	transition: padding-right 0.22s ease-out;
}

@media ( prefers-reduced-motion: reduce ) {
	html.lbr-rvp-drawer-open body { transition: none; }
}

/* On a phone the drawer is a bottom sheet, so there is nothing to move aside. */
@media ( max-width: 600px ) {
	html.lbr-rvp-drawer-open body { padding-right: 0; }
}

/* Success: the tick draws itself, then the words arrive. */
.lbr-rvp-report-success {
	text-align: center;
	padding: 28px 4px 8px;
}

.lbr-rvp-tick {
	width: 68px;
	height: 68px;
	display: block;
	margin: 0 auto 14px;
}

.lbr-rvp-tick-ring {
	stroke: #1a9c5b;
	stroke-width: 2.5;
	stroke-dasharray: 145;
	stroke-dashoffset: 145;
	animation: lbr-rvp-ring 0.45s cubic-bezier(0.65, 0, 0.45, 1) forwards;
}

.lbr-rvp-tick-check {
	stroke: #1a9c5b;
	stroke-width: 3.5;
	stroke-linecap: round;
	stroke-linejoin: round;
	stroke-dasharray: 38;
	stroke-dashoffset: 38;
	animation: lbr-rvp-check 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.4s forwards;
}

.lbr-rvp-report-success .lbr-rvp-report-thanks {
	opacity: 0;
	animation: lbr-rvp-thanks 0.3s ease-out 0.62s forwards;
}

@keyframes lbr-rvp-ring  { to { stroke-dashoffset: 0; } }
@keyframes lbr-rvp-check { to { stroke-dashoffset: 0; } }
@keyframes lbr-rvp-thanks {
	from { opacity: 0; transform: translateY(4px); }
	to   { opacity: 1; transform: none; }
}

@media ( prefers-reduced-motion: reduce ) {
	.lbr-rvp-tick-ring,
	.lbr-rvp-tick-check { animation: none; stroke-dashoffset: 0; }
	.lbr-rvp-report-success .lbr-rvp-report-thanks { animation: none; opacity: 1; }
}

.lbr-rvp-modal-box--image {
	background: transparent;
	box-shadow: none;
	padding: 0;
	overflow: visible;
	max-width: none;
}

.lbr-rvp-modal-cover {
	display: block;
	max-height: 84vh;
	max-width: min(560px, 90vw);
	width: auto;
	border-radius: 10px;
	box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45);
}

.lbr-rvp-modal-box--text h3 {
	font-family: 'Lora', Georgia, serif;
	font-size: 20px;
	margin: 0 0 14px;
}

.lbr-rvp-modal-box--text p {
	font-size: 15px;
	line-height: 1.7;
	margin: 0 0 1em;
}

.lbr-rvp-modal .lbr-rvp-modal-close {
	position: absolute;
	top: 10px;
	right: 10px;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	border: 0;
	padding: 0;
	min-height: 0;
	background: #fff;
	color: #1f2937;
	font-size: 14px;
	line-height: 1;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
	z-index: 1;
}

.lbr-rvp-modal-box--image .lbr-rvp-modal-close {
	top: -12px;
	right: -12px;
}

/* — Small screens: single column, cover modest and centred — */

@media (max-width: 700px) {
	.lbr-rvp-cols {
		grid-template-columns: 1fr;
		gap: 24px;
	}

	.lbr-rvp-head {
		position: static;
		padding-top: 0;
		padding-bottom: 0;
		/* Nothing sticks at this width, so nothing needs to paint over
		   scrolling text — and the JS that measures the page's real
		   colour returns early here for that same reason, leaving the
		   var unset and the #fff fallback showing as a white card on an
		   off-white page. No pinning, no background. */
		background: transparent;
	}

	.lbr-rvp-head::after {
		display: none;
	}

	/* Stacked, the side column has the whole width to itself and no
	   reason to sit in a 240px lane: the metadata table and the
	   publisher's description are text, and text wants the column. */
	.lbr-rvp-side {
		position: static;
		max-width: none;
		margin: 0;
		width: 100%;
	}

	/* The cover is the exception — it stays a shade narrower than the
	   text beside it, because a full-bleed cover reads as a banner
	   rather than as the book. */
	/* .lbr-rvp-cover-btn is reset with margin:0 by a two-class selector,
	   and a media query adds no specificity — so the auto margins were
	   losing and the cover sat left. Matched weight, and it centres. */
	.lbr-rvp .lbr-rvp-cover-btn,
	.lbr-rvp .lbr-rvp-cover {
		max-width: 300px;
		margin-left: auto;
		margin-right: auto;
	}

	.lbr-rvp-meta,
	.lbr-rvp-blurb {
		max-width: none;
	}
}

/* Gutters in step with the app's: 18px at the width where the phone is
   being held against them. */
@media (max-width: 640px) {
	.lbr-rvp {
		padding-left: 18px;
		padding-right: 18px;
	}
}

/* — The way back: a breadcrumb chip at the top of the review — */

.lbr-rvp .lbr-rvp-backpill {
	display: inline-block;
	margin: 0 0 18px;
	padding: 7px 16px;
	border-radius: 999px;
	border: 1px solid var(--rvp-border);
	background: #fff;
	color: var(--rvp-accent);
	font-family: var(--rvp-sans);
	font-size: 13px;
	font-weight: 600;
	text-decoration: none;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.lbr-rvp .lbr-rvp-backpill:hover {
	color: var(--rvp-accent);
	border-color: var(--rvp-accent);
	box-shadow: 0 2px 8px rgba(31, 41, 55, 0.1);
}

/* ————— Problem report (testers' flag) ————— */

.lbr-rvp .lbr-rvp-report {
	/* Two actions that had been stacking flush against each other. They
	   are offers, not part of the review, so they sit centred and apart
	   — and wrap rather than squeeze when the column is narrow. */
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 10px;
	margin: 0 0 24px;
}

.lbr-rvp .lbr-rvp-report-btn {
	background: none;
	border: 1px dashed #c9cdd4;
	border-radius: 8px;
	padding: 7px 14px;
	font-size: 13px;
	color: #6b7280;
	cursor: pointer;
	line-height: 1.4;
}

.lbr-rvp .lbr-rvp-report-btn:hover {
	border-color: #283B91;
	color: #283B91;
	background: rgba(40, 59, 145, 0.04);
}

.lbr-rvp .lbr-rvp-report-flag {
	margin-right: 6px;
}

.lbr-rvp-report-form label {
	display: block;
	font-size: 13px;
	font-weight: 600;
	margin: 14px 0 4px;
}

.lbr-rvp-report-form select,
.lbr-rvp-report-form textarea {
	width: 100%;
	font: inherit;
	font-size: 14px;
	padding: 8px 10px;
	border: 1px solid #c9cdd4;
	border-radius: 8px;
	background: #fff;
}

/*
 * The select had no indicator that it was one. Themes routinely set
 * `appearance: none` on form controls, which removes the native arrow, and the
 * rule above then paints a flat white background over anything left — so the
 * control read as a text input showing "Duplicate review" rather than as a
 * menu. Rather than hope the theme leaves the native widget alone, we opt out
 * of it deliberately and draw our own chevron, which looks the same in every
 * browser and cannot be undone by a theme we do not control.
 */
.lbr-rvp-report-form select {
	-webkit-appearance: none;
	-moz-appearance: none;
	appearance: none;
	padding-right: 34px;
	cursor: pointer;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%236b7280' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 12px center;
	background-size: 12px 8px;
}

/* Chrome/Safari draw a second arrow of their own on some platforms. */
.lbr-rvp-report-form select::-ms-expand {
	display: none;
}

.lbr-rvp-report-form .lbr-rvp-report-send {
	margin-top: 14px;
	background: #283B91;
	color: #fff;
	border: 0;
	border-radius: 999px;
	padding: 9px 22px;
	font-size: 14px;
	cursor: pointer;
}

.lbr-rvp-report-form .lbr-rvp-report-send:disabled {
	opacity: 0.6;
	cursor: default;
}

.lbr-rvp-report-form .lbr-rvp-report-status {
	color: #b3261e;
	font-size: 13px;
	margin: 10px 0 0;
	min-height: 1em;
}

.lbr-rvp-report-form .lbr-rvp-report-thanks {
	font-size: 15px;
	margin: 8px 0;
}

/* Type-driven report form additions. */
.lbr-rvp-report-form input[type="text"],
.lbr-rvp-report-form input[type="url"] {
	width: 100%;
	font: inherit;
	font-size: 14px;
	padding: 8px 10px;
	border: 1px solid #c9cdd4;
	border-radius: 8px;
	background: #fff;
}

.lbr-rvp-report-form .lbr-rvp-report-deflect {
	font-size: 14px;
	line-height: 1.55;
	background: #f5f7fa;
	border-left: 3px solid #283B91;
	border-radius: 0 8px 8px 0;
	padding: 12px 14px;
	margin: 14px 0 4px;
	color: #3c4048;
}

/* Bookshelf save button — sibling of the report flag; saved state fills. */
.lbr-rvp .lbr-rvp-save-btn {
	margin-right: 10px;
}

.lbr-rvp .lbr-rvp-save-btn--saved {
	border-style: solid;
	border-color: #283B91;
	color: #283B91;
	background: rgba(40, 59, 145, 0.05);
}

/* Bookshelf gold on the review page: bigger glyphs, saved = soft gold
   wash. The report flag grows to match. */
.lbr-rvp .lbr-rvp-save-btn span,
.lbr-rvp .lbr-rvp-report-flag {
	font-size: 17px;
	vertical-align: -1px;
}

.lbr-rvp .lbr-rvp-save-btn--saved {
	border-style: solid;
	border-color: #d9a406;
	color: #a87d00;
	background: rgba(217, 164, 6, 0.12);
}

.lbr-rvp .lbr-rvp-save-btn--saved span {
	color: #d9a406;
}

/* The star itself is the shared rounded SVG drawing: outline in the
   button's text colour until saved, then solid gold. */
.lbr-rvp .lbr-rvp-save-btn span svg {
	width: 17px;
	height: 17px;
	vertical-align: -3px;
}

.lbr-rvp .lbr-rvp-save-btn span svg path {
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linejoin: round;
	stroke-linecap: round;
}

.lbr-rvp .lbr-rvp-save-btn--saved span svg path {
	fill: #d9a406;
	stroke: #d9a406;
}

.lbr-rvp-modal .lbr-rvp-confirm-msg {
	margin: 2px 0 0;
	font-size: 16px;
}

.lbr-rvp-confirm-row {
	display: flex;
	gap: 12px;
	margin-top: 16px;
}

.lbr-rvp-confirm-row .lbr-rvp-confirm-keep {
	background: none;
	border: 1px solid #c9cdd4;
	border-radius: 999px;
	padding: 9px 20px;
	font-size: 14px;
	cursor: pointer;
}

.lbr-rvp-confirm-row .lbr-rvp-report-send {
	margin-top: 0;
	background: #b3261e;
}

/* Saved stays gold even under the hover wash. */
.lbr-rvp .lbr-rvp-save-btn--saved:hover {
	background: rgba(217, 164, 6, 0.18);
	border-color: #d9a406;
	color: #a87d00;
}

/* The Keep button must actually say "Keep it" — the theme's default
   button colour is white-on-transparent, which rendered it blank. */
.lbr-rvp-confirm-row .lbr-rvp-confirm-keep {
	color: #3c4048;
	font: inherit;
	font-size: 14px;
	transition: background 0.15s ease, border-color 0.15s ease;
}

/* Both confirm buttons answer the pointer: Keep with a soft grey wash,
   Remove by deepening its red. The theme offers no hover of its own
   here, so without these the buttons feel dead. */
.lbr-rvp-confirm-row .lbr-rvp-confirm-keep:hover {
	background: #f1f2f5;
	border-color: #9aa0a8;
	color: #1f2937;
}

.lbr-rvp-confirm-row .lbr-rvp-report-send {
	transition: background 0.15s ease;
}

.lbr-rvp-confirm-row .lbr-rvp-report-send:hover {
	background: #9c1f18;
	color: #fff;
}

/* The rail stars are revealed by hovering their card, and touch has no
   hover — so on a phone the save affordance was there in the markup and
   invisible on screen, which reads as the feature simply not existing
   on this page. Same treatment the app grid gets: always visible where
   there is nothing to hover with, full strength once saved. */
@media (hover: none) {
	.lbr-rvp-card-star {
		opacity: 0.45;
	}

	.lbr-rvp-card-star--saved {
		opacity: 1;
	}
}
