@charset "utf-8";

:root {
	--color-primary: #2B5442;
    --color-primary-light: #E0E8E4;
    --color-primary-dark: #1F3D2F;
	--color-secondary: #E5A15D;
    --color-secondary-dark: #b8743a;
    --color-secondary-light: #fce8dc;
    --color-tertiary: #5B6B85;        /* slate blue — main */
    --color-tertiary-dark: #44546B;   /* hover / pressed */
    --color-tertiary-light: #E8ECF2;  /* tinted backgrounds */
	--color-background: #F9F8F6;
    --color-background-dark: #ece9e3;
	--color-text: #333;
	--color-muted: #666;
    --color-muted-light: #999;
	--color-border: #ddd;
	--color-highlight: #feb;
    --color-coral:      #993C1D;
    --color-coral-light: #fde6dd;   /* tinted, for future use */
    --color-coral-dark:   #7A2F15;
}

* {
    box-sizing: border-box;
    /* margin: 0;*/
    padding: 0;
}

body {
    min-height: 100vh;
    background: var(--color-background);
	font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
    color: var(--color-text);
	margin: 0;
}

a:link {
	color: var(--color-primary);
	text-decoration: none;
}

a:visited {
	color: var(--color-primary);
	text-decoration: none;
}

a:hover {
	text-decoration: underline;
}

li {
	margin-inline-start: 1rem;
}

/* Desktop layout */
.layout {
    display: grid;
    grid-template-columns: minmax(180px, 240px) 1fr minmax(180px, 240px);
    min-height: 100vh;
}

/* ---------- Site footer ----------
   Visually distinct band at the bottom of every page. A tinted darker
   background gives it weight; columns are an auto-fit grid so they
   gracefully collapse from 3 → 2 → 1 as the viewport narrows, without
   needing media queries for column count. A separate "bottom" row
   carries the address + copyright. */

/* Two-layer approach to mirror .content's horizontal position above:
   - .footer (outer) reserves the same left/right space the sidebars
     occupy in the grid above. The tinted band still spans the full
     viewport via background, but its padding pushes the contents
     inward by the sidebar widths.
   - .footercontent (inner) then mirrors .content's own constraints:
     max-width: 1280px and margin: 0 auto, so on wide viewports it
     centres within the middle "column" exactly as .content does.
   Media-query overrides below adjust as each sidebar becomes a drawer. */
.footer {
    width: 100%;
    background: var(--color-background-dark);
    border-top: 1px solid var(--color-border);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
    /* Pad outer by the sidebar widths — left sidebar on the left,
       right sidebar on the right. Matches the desktop grid:
       minmax(180px, 240px) 1fr minmax(180px, 240px). */
    padding-left: 240px;
    padding-right: 240px;
}

.footercontent {
    max-width: 1280px;
    margin: 0 auto;
    padding: 2.5rem 1rem 1.5rem;
    font-size: 0.875rem;
    line-height: 1.6;
    color: var(--color-text);
}

.footercolumns {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: 2rem 2.5rem;
    margin-bottom: 2rem;
}

.footercolumn__heading {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1rem;
    font-weight: bold;
    color: var(--color-primary);
    margin: 0 0 0.75rem 0;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--color-border);
    letter-spacing: 0.01em;
}

.footercolumn__list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.footercolumn__list li {
    margin: 0;
    padding: 0;
}

.footercolumn__list li + li {
    margin-top: 0.4rem;
}

/* Link colours — neutral default, primary on hover/focus for affordance. */
.footercontent a {
    color: var(--color-text);
    text-decoration: none;
    transition: color 0.15s;
}

.footercontent a:hover,
.footercontent a:focus-visible {
    color: var(--color-primary);
    text-decoration: underline;
}

.footercontent a:visited {
    color: var(--color-text);
}

.footercontent a:visited:hover {
    color: var(--color-primary);
}

/* ---------- Footer bottom row ---------- */

.footerbottom {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem 1.5rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--color-border);
    font-size: 0.8125rem;
    color: var(--color-muted);
}

/* Reset <address> default italic; we want a flat label-like treatment. */
.footerbottom__address {
    font-style: normal;
    margin: 0;
    line-height: 1.5;
    max-width: 28rem;
}

.footerbottom__address strong {
    color: var(--color-text);
    margin-right: 0.25rem;
}

.footerbottom__copyright {
    margin: 0;
    line-height: 1.5;
}

.footerbottom__copyright a {
    font-weight: bold;
}

.alert {
	background: #6c3;
	color: #fff;
	padding: 1rem;
	font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
	z-index: 10;
	display: none;
	position: absolute;
	inset-inline: 0;
	margin-left: 1rem;
	margin-right: 1rem;
	font-weight: bold;
	border-top-left-radius: 1rem;
	border-top-right-radius: 1rem;
}

.sidebar {
    background: #fff;
    padding: 1rem;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    z-index: 200;
    transition: transform 0.25s ease;
}

.sidebar-left {
    border-right: 1px solid var(--color-border);
}

.sidebar-right {
    border-left: 1px solid var(--color-border);
}

.content {
    padding: 1rem;
    max-width: 1280px;
    margin: 0 auto;
    width: 100%;
    min-width: 0;
    position: relative;
}

.hamburger-left.close {
	display: none;
}

.hamburger-right.close {
	display: none;
}

.hamburger {
    display: none;
    position: fixed;
    z-index: 300;
    background: #fff;
    border: 1px solid #ddd;
    border-radius: 6px;
    width: 36px;
    height: 36px;
    cursor: pointer;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    top: 12px;
}

.hamburger-left {
    left: 12px;
}

.hamburger-right {
    right: 12px;
}

.hamburger span {
    display: block;
    width: 16px;
    height: 1.5px;
    background: #333;
    border-radius: 2px;
}

.overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.35);
    z-index: 150;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
}

.overlay.open {
    opacity: 1;
    pointer-events: all;
}

.logo {
	max-width: 75%;
	height: auto;
	margin-bottom: 1rem;
}

.errormessage {
	font-size: 1rem;
	color: #f30;
	font-weight: bold;
	padding-bottom: 0.5rem;
}

.herotext {
	margin: 0em;
	float: left;
	width: auto;
	background-color: rgba(255, 255, 255, 1);
	padding: 1em;	
	border-bottom-right-radius: 1em;
	border: 1px solid #999;
	max-width: 50em;
	min-height: 1em;
}

.loginhero {
	height: 250px;
	background: url(/images/friends_cafe.jpg) left;
	background-size: cover;
	min-width: 18em;
	padding: 1em;
	border: var(--color-border) solid 1px;
    border-radius: 1rem;
	margin-bottom: 1rem;
}

.bloghero {
	height: 250px;
	background: url(/images/lovebooks.webp) left;
	background-size: cover;
	min-width: 18em;
	padding: 1em;
	border: var(--color-border) solid 1px;
    border-radius: 1rem;
	margin-bottom: 1rem;
}

.feedhero {
	height: 250px;
	background: url(/images/lovebooks.webp) left;
	background-size: cover;
	min-width: 18em;
	padding: 1em;
	border: var(--color-border) solid 1px;
    border-radius: 1rem;
	margin-bottom: 1rem;
}

.abouthero {
	height: 250px;
	background: url(/images/lovebooks.webp);
	background-size: cover;
	min-width: 18em;
	padding: 1em;
	border: var(--color-border) solid 1px;
    border-radius: 1rem;
	margin-bottom: 1rem;
}

.safetyhero {
	height: 250px;
	background: url(/images/safety.png);
	background-size: cover;
	min-width: 18em;
	padding: 1em;
	border: var(--color-border) solid 1px;
	border-radius: 1rem;
	margin-bottom: 1rem;
}

.greenhero {
	height: 250px;
	background: url(/images/subjects/green.jpg);
	background-size: cover;
	min-width: 18em;
	padding: 1em;
	border-bottom: var(--color-border) solid 1px;
	border-radius: 1rem;
	margin-bottom: 1rem;
}

.scholarshiphero {
	height: 250px;
	background: url(/images/scholarship.png);
	background-size: cover;
	min-width: 18em;
	padding: 1em;
	border-bottom: var(--color-border) solid 1px;
	border-radius: 1rem;
	margin-bottom: 1rem;
}

.pagenavtoolbar {
	font-size: 1em;
	margin-bottom: 0.5em;	
	clear: left;
	overflow: auto;
}

.pagenavbutton {
	border: 1px solid var(--color-muted);
	padding: 0.5em;
	font-size: 0.75em;
	float: left;
	background: #ccc;
	margin-right: 0.25em;
	cursor: pointer;
	border-radius: 3px;
}

.pagenavbutton:hover {
	background: #fff;	
}

.pagenavbuttondisabled {
	color: #666;
	cursor: pointer;
	background: #eee;
	border: 1px solid var(--color-muted);
	padding: 0.5em;
	font-size: 0.75em;
	float: left;
	margin-right: 0.25em;
	border-radius: 3px;
	cursor: default;
}

.pagenavbuttonellipsis {
	color: #666;
	cursor: pointer;
	padding: 0.5em;
	font-size: 0.75em;
	float: left;
	margin-right: 0.25em;
	border-radius: 3px;
	cursor: default;
}

.pagenavpagenumber {
	padding-top: 0.25em;
	padding-right: 1em;
	padding-left: 0.5em;
	float: left;
}

.blogimage {
	background: #fff;
	padding: 1em;
	border: 1px solid var(--color-border);
	font-size: 0.75em;
	color: #333;
	border-radius: 0.5em;
    margin-bottom: 1rem;
}

.blogimage img {
	width: 100%;
	border-radius: 0.5em;
	height: auto;
}

.blogitem {
	float: left;
	clear: both;
	margin-bottom: 0.5em;
	background: #fff;
	padding: 1rem;	
	border: 1px solid var(--color-border);
	border-radius: 1em;
}

.blogitemimg {
	width: 200px;
	float: left;
	background: #fff;
	padding: 0.5em;
	margin-right: 0.5em;
	margin-bottom: 0.5em;
	border: 1px solid var(--color-border);
	border-radius: 0.25em;
}

.blogitem img {
	width: 100%;
}

.affiliatebutton {
    background: #feb;
    width: auto;
    padding: 1em;
    /* display: inline-block; */
    color: #000;
    border: 1px solid #999;
	border-radius: 0.25em;
	cursor: pointer;
	font-weight: bold;
	float: left;
	clear: both;
	margin: 1em 0;
}

.affiliatebutton a:link {
	color: black;
}

.affiliatebutton:hover {
	background: #fc6;
}

.blogcategorytag {
    border: 1px solid var(--color-border);
    border-radius: 0.25em;
    padding: 0.5em;
    font-size: .75em;
    color: #333;
    background: #eee;
    display: inline-block;
    margin-top: 1em;
}

.bookcontent {
	overflow: auto;
	min-width: 0;
}

.bookcontent h2, .bookcontent h3 {
	margin: 0.5rem 0 0.5rem 0;
}

.bookinfomain {
    width: 100%;
    border-radius: 1rem;
    background: #fff;
    padding: 1rem;
    border-bottom: 1px solid var(--color-muted);
    display: flow-root;
}

.bookinforow{
	display: flex;
}

.bookinfodetailssubjects {
	font-size: 0.75rem;
	color: var(--color-secondary);
	margin-bottom: 1rem;
	display: block;
	text-transform: uppercase;
	font-weight: bold;
}

.bookinfodetailsauthorby {
	color: var(--color-muted);
}

.bookinfosummary {
	font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
	font-size: 1rem;
	color: #333;
	background: #fff;
	border-radius: 1rem;
	border-bottom: 1px solid var(--color-muted);
	padding: 1rem;
	margin-top: 1rem;
	flex: 1;
}

/* Book details on the right sidebar */
.bookinfodetails { 
	font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
	font-size: 0.875rem;
	background: #fff;
	border-radius: 1rem;
	border-bottom: 1px solid var(--color-muted);
	padding: 1rem;
	margin: 1rem 0rem 0rem 1rem;
	width: 300px;
	height: fit-content;
}

.bookinfodetailsrow {
	display: flex;
	margin-bottom: 0.5rem;
}

.bookinfodetailstitle {
	color: var(--color-muted);
	font-size: 0.75rem;
}

.bookinfodetailsicon {
	width: 1.5rem;
	height: 1.5rem;
	float: left;
	margin-right: 0.5em;
}

.bookinfodetailsdata {
	float: left;
}

.bookinfodetailsicon svg {
	width: 100%;
	color: var(--color-muted);
	height: auto;
}

.booktitle {
	font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
	font-weight: bold;
	font-size: 1.5em;
}

/* Long-title fit: step the book title (h1) down by length so very long
   titles don't tower over the cover. The bucket class is set in book.php
   from the title's character count; shrink-only -- short titles get no
   class and keep the default size. Mobile values are in the 640px block.
   Carries .bookcontent so it outranks the .bookcontent h1 rule. */
.bookcontent h1.booktitle--long   { font-size: 1.7rem; }
.bookcontent h1.booktitle--xlong  { font-size: 1.45rem; }
.bookcontent h1.booktitle--xxlong { font-size: 1.2rem; }

.bookimage {
	float: left; 
	border: 0px solid var(--color-muted);
	min-height: 120px;
	border-radius: 0.5em;
	width: 120px;
}

.bookimage img {
	width: 100%;
	display: block;
	border-radius: 0.5em;
	height: auto;
}

.bookimageprimary {
	float: left; 
	margin-right: 1em;
	border: 1px solid #999;
	border-radius: 0.5em;
	width: 120px;
	min-height: 100px;
}

.bookimageprimary img {
	width: 100%;
	display: block;
	border-radius: 0.5em;
	height: auto;
}

.bookresult {
	font-family: 'Libre Baskerville', 'Playfair Display', Georgia, "Times New Roman", Times, serif;
	padding: 0.5em;
	font-size: 0.8em;
	color: #555;
	cursor: pointer;
	border-bottom: 1px solid #999;
	overflow: auto;
}

.breadcrumb {
	font-size: 1rem;
	color: #555;
	margin: 0rem 0 0rem 0;
}

/* Booklist styles */

.booklisttab {
	padding: 0.5rem;
	font-size: 0.875rem;
	color: #555;
	cursor: pointer;
	border-bottom: 1px solid var(--color-muted);
	overflow: auto;
	float: left;
	border-radius: 0.5em;
	margin: 0rem 0.5rem 0.5rem 0rem;
	background: #fff;
}

.booklisttab.active {
	background: var(--color-primary);
	color: #fff;
}

.booklisttab:hover {
	background: var(--color-primary);
	color: #fff;
}

.booklisttabtitle {
	float: left;
	padding: 0.25rem;
}

.booklisttabcount {
	float: right;
	color: #fff;
	border-radius: 0.5em;
	background: var(--color-primary);
	padding: 0.25rem;
	min-width: 1.5em;
	margin-left: 1rem;
	text-align: center;
}

.booklisttabicon {
    display: inline-block;
    width: 1rem;
    height: 1rem;
    margin-right: 0.4rem;
    vertical-align: -0.15rem; /* visually align with text baseline */
    color: currentColor;
}

.booklisttabicon svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* ============================================================
   Booklist book cards — grid layout, fixed aspect ratio cover,
   lift-on-hover. Replaces the older float-based layout.
   ============================================================ */

.booklistbooks {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
    gap: 0.75rem;
    clear: left;
    margin-top: 0.5rem;
}

.booklistbook {
    display: flex;
    align-items: stretch;
    gap: 0.75rem;
    background: #fff;
    padding: 0.75rem;
    border-bottom: 1px solid var(--color-muted);
    border-radius: 0.6rem;
    height: 7.5rem;
    font-size: 0.825rem;
    cursor: pointer;
    transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
    overflow: hidden;
}

.booklistbook:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.08);
    border-color: var(--color-secondary);
}

.booklistbooks > a:hover {
    text-decoration: none;
}

.booklistbookcover {
    flex-shrink: 0;
    width: 4.25rem;
    aspect-ratio: 2 / 3;
    border-radius: 0.4rem;
    overflow: hidden;
    background: var(--color-background);
    border: 1px solid var(--color-border);
}

.booklistbookcover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.booklistbookbody {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    overflow: hidden;
}

.booklistbooktitle {
    font-weight: bold;
    color: var(--color-primary);
    font-family: 'Libre Baskerville', Georgia, "Times New Roman", Times, serif;
    line-height: 1.25;
    margin-bottom: 0.2rem;
    /* 2-line clamp so longer titles don't push the card height around. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
}

.booklistbook .booklistbooktitle {
    padding-right: 1rem;
}

.booklistbookauthor {
    color: var(--color-muted);
    font-size: 0.825rem;
    line-height: 1.3;
    /* 2-line clamp for authors with multiple names too. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Subject pill — one pill per card. Mirrors .searchresult__subject
   styling so the two pages render consistently. Limited to one pill
   in PHP because the card's fixed 7.5rem height can't fit a wrapping
   row; the full subjects list is exposed via the data-subjects
   attribute on .booklistbook so the on-page filter still matches
   against hidden subjects. */
.booklistbook__subjects {
    display: flex;
    gap: 0.3rem;
    margin-top: 0.35rem;
    min-width: 0;  /* allow the child to shrink and ellipsise */
}

.booklistbook__subject {
    display: inline-block;
    font-size: 0.7rem;
    padding: 0.15rem 0.55rem;
    background: var(--color-background);
    color: var(--color-muted);
    border-radius: 1rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: bold;
    /* Cap the pill width so a single very long subject (e.g.
       "Historical Fiction — 20th Century") ellipsises rather than
       pushing the row wide. */
    max-width: 10rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.booklistcontrolpanel {
	overflow: auto;
	margin-bottom: 0.5rem;
	clear: both;
	background: #fff;
	padding: 0.5rem;
	border-bottom: 1px solid var(--color-muted);
	border-radius: 0.5em;
}

.booklistselect {
	margin-top: 0px;
	padding: 0.5rem;
	font-size: 0.875rem;
	border: 1px solid var(--color-primary);
	border-radius: 0.5em;
	font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
	color: #fff;
	background-color: var(--color-primary);
	height: 2.5rem;
}

.booklistselect option {
	background-color: #fff;
	color:#333;
}

.booklistselect option:hover {
	background-color: #eee;
}

.bookcontrolpanel {
	margin-top: 1rem;
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex-wrap: wrap;
}

.booklistsidebar {
	width: 100%;
	font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
	color: var(--color-muted);
	text-align: right;
	font-size: 0.875rem;
	margin-top: 1rem;
	background-color: #fff;
	padding: 1rem;
	border-bottom: 1px solid var(--color-muted);
	border-radius: 1rem;
}

.booksharebutton {
	margin-top: 0px;
	background: #fff;
	color: var(--color-primary);
	padding: 0.5rem;
	border-radius: 0.5em;
	border: 1px solid var(--color-primary);
	font-size: 0.875rem;
	cursor: pointer;
	background-color: var(--color-background);
	align-items: center;
	display: inline-flex;
	gap: 0.25rem;
	height: 2.5rem;
}

.booksharebutton:hover {
	background: var(--color-secondary);
	color: #fff;
	border: 1px solid var(--color-secondary);
}

.booksharebutton svg {
	width: 1em;
	height: 1em;
}

.bookfavoritebutton {
	margin-top: 0px;
	background: var(--color-background);
	color: var(--color-primary);
	padding: 0.5rem;
	border-radius: 0.5em;
	font-size: 0.875rem;
	cursor: pointer;
	border: 1px solid var(--color-muted);
	align-items: center;
	display: inline-flex;
	gap: 0.25rem;
	height: 2.5rem;
}

/* Not favorited + hover: primary green ("click to add"). */
.bookfavoritebutton:hover {
    background: var(--color-background-dark);
    color: var(--color-primary);
    border: 1px solid var(--color-muted);
}

/* Click feedback — small scale-down for tactile feel. */
.bookfavoritebutton:active {
    transform: scale(0.96);
}

.bookfavoritebutton svg {
	width: 1em;
	height: 1em;
}

/* ============================================================
   "More by this author" shelf — horizontal scrolling row of
   book covers with title underneath, displayed below the
   main book content area.
   ============================================================ */

.morebyauthor {
    margin-top: 1rem;
    background: #fff;
    border-radius: 1rem;
    border-bottom: 1px solid var(--color-muted);
    padding: 1.5rem;
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
    box-sizing: border-box;
}

.morebyauthor__title {
    margin: 0 0 1rem 0;
    color: var(--color-primary);
    font-size: 1.25rem;
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
}

.morebyauthor__shelf {
    display: flex;
    gap: 1rem;
    overflow-x: auto;
    padding: 0.25rem 0 1rem 0;
    max-width: 100%;
    min-width: 0;
    /* Smooth touch-scroll on iOS, snap to cards. */
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
    scrollbar-color: var(--color-border) transparent;
}

.morebyauthor__shelf::-webkit-scrollbar {
    height: 6px;
}

.morebyauthor__shelf::-webkit-scrollbar-track {
    background: transparent;
}

.morebyauthor__shelf::-webkit-scrollbar-thumb {
    background: var(--color-border);
    border-radius: 3px;
}

.morebyauthor__shelf::-webkit-scrollbar-thumb:hover {
    background: var(--color-muted);
}

.morebyauthor__card {
    flex-shrink: 0;
    width: 8rem;
    text-decoration: none;
    color: inherit;
    scroll-snap-align: start;
    transition: transform 0.15s;
}

.morebyauthor__card:hover {
    text-decoration: none;
    transform: translateY(-2px);
}

.morebyauthor__card:link,
.morebyauthor__card:visited {
    color: var(--color-text);
}

.morebyauthor__cover {
    width: 100%;
    aspect-ratio: 2 / 3;
    border: 1px solid var(--color-border);
    border-radius: 0.4rem;
    overflow: hidden;
    background: var(--color-background);
    margin-bottom: 0.5rem;
}

.morebyauthor__cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.morebyauthor__title-text {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 0.85rem;
    line-height: 1.3;
    color: var(--color-primary);
    /* 2-line clamp so longer titles don't push the card height around. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.morebyauthor__card:hover .morebyauthor__title-text {
    text-decoration: underline;
}

/* ============================================================
   "Write/Edit a review" button on the book page — append to
   your stylesheet next to .bookfavoritebutton / .booksharebutton.
   ============================================================ */

.bookreviewbutton {
    margin-top: 0px;
    background: #fff;
    color: var(--color-primary);
    padding: 0.5rem;
    border-radius: 0.5em;
    border: 1px solid var(--color-primary);
    font-size: 0.875rem;
    cursor: pointer;
    background-color: var(--color-background);
    align-items: center;
    display: inline-flex;
    gap: 0.25rem;
    height: 2.5rem;
    font-family: inherit;
    text-decoration: none;
}

.bookreviewbutton:link,
.bookreviewbutton:visited {
    color: var(--color-primary);
}

.bookreviewbutton:hover {
    background: var(--color-secondary);
    color: #fff;
    border: 1px solid var(--color-secondary);
    text-decoration: none;
}

.bookreviewbutton svg {
    width: 1em;
    height: 1em;
}

/* Favorited (resting) — secondary orange. */
.bookfavorited {
    background: var(--color-secondary);
    color: #fff;
    border: 1px solid var(--color-secondary);
}

/* Favorited + hover: darker orange ("click to remove"). */
.bookfavorited:hover {
    background: var(--color-secondary-dark);
    color: #fff;
    border: 1px solid var(--color-secondary-dark);
}

.mobilelogo {
	display: none;
    position: relative;
    z-index: 150; /* above sidebars (200), below hamburgers (300) */
}

.mobilelogo img {
	height: 3rem;
	width: auto;
	margin-top: 0.5rem;
	margin-left: 4rem;
    display: block;
}

.mobilelogo a {
    display: inline-block;
}

.navbutton {
	padding: 0.75rem;
	font-size: 0.875rem;
	color: var(--color-primary);
	background: var(--color-background);
	margin-bottom: 0.5rem;
	cursor: pointer;
	border-radius: 1rem;
	display: flex;
	align-items: center;
}

.navbutton.active {
	background: var(--color-primary);
	color: #fff;
}	

.navbutton.active:visited {
	background: var(--color-primary);
	color: #fff;
}	

.navbutton:link {
	color: var(--color-primary);
}

.navbutton:hover {
	background: var(--color-primary);
	color: #fff;
	text-decoration: none;
}

.navbutton:visited {
	color: var(--color-primary);
}

.navbutton:visited:hover {
	color: #fff;
}

.searchbar {
	width: 100%;
	padding: 1rem;
	border: 1px solid var(--color-border);
	border-radius: 1em;
	font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
	color: #333;
	background-color: var(--color-background);
	margin-bottom: 1rem;
}

/* ============================================================
   Search bar wrapper — visual container that joins the input
   and the submit button into a single rounded element. The
   input keeps its own borders for accessibility (screen-reader
   focus states stay clear), but visually they read as one.
   ============================================================ */

.searchbarwrap {
    position: relative;
    display: flex;
    align-items: stretch;
    margin-bottom: 1rem;
}

/* Override the existing .searchbar margin-bottom since the
   wrapper handles spacing now. The input also loses its right
   border-radius and right border so it merges cleanly with
   the button. */
.searchbarwrap .searchbar {
    flex: 1;
    margin-bottom: 0;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    border-right: none;
    /* Slightly less padding on the right since the button
       now occupies that visual space. */
    padding-right: 0.5rem;
}

.searchbarbutton {
    flex-shrink: 0;
    background: var(--color-primary);
    color: #fff;
    border: 1px solid var(--color-primary);
    border-top-right-radius: 1em;
    border-bottom-right-radius: 1em;
    padding: 0 0.5rem;
    cursor: pointer;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, border-color 0.15s;
}

.searchbarbutton:hover {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
}

.searchbarbutton:focus {
    outline: 2px solid var(--color-secondary);
    outline-offset: 1px;
}

.searchbarbutton svg {
    width: 1.1rem;
    height: 1.1rem;
}

.searchbar::-webkit-search-decoration,
.searchbar::-webkit-search-cancel-button,
.searchbar::-webkit-search-results-button,
.searchbar::-webkit-search-results-decoration {
    -webkit-appearance: none;
}

/* ============================================================
   Follow / unfollow components — append to your stylesheet
   ============================================================ */

/* ---------- The full follow button ----------
   Used on the public profile page next to (or under) the username.
   Two states: not-following (primary green) and following (secondary
   ghost). Following + hover transforms to "Unfollow" with a danger tint. */

.followbutton {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem 1rem;
    border-radius: 0.5rem;
    font-size: 0.9rem;
    font-weight: bold;
    cursor: pointer;
    border: 1px solid var(--color-primary);
    background: var(--color-primary);
    color: #fff;
    font-family: inherit;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
    text-decoration: none;
}

.followbutton:link,
.followbutton:visited {
    color: #fff;
}

.followbutton:hover {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
    text-decoration: none;
}

.followbutton:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* "Following" state — ghost-style. */
.followbutton--following {
    background: #fff;
    color: var(--color-primary);
    border-color: var(--color-primary);
}

.followbutton--following:link,
.followbutton--following:visited {
    color: var(--color-primary);
}

.followbutton--following:hover {
    background: #fff;
}

/* Hover transformation: "Following" -> "Unfollow", danger tint. */
.followbutton.followbutton--hoverunfollow {
    background: #fff;
    color: #c00;
    border-color: #c00;
}

/* "+/✓" pseudo-icon via the .followbutton__icon span. Uses CSS
   instead of an SVG so it can change with state without DOM swaps. */
.followbutton__icon::before {
    content: "＋";
    font-weight: bold;
    font-size: 0.9rem;
    line-height: 1;
}

.followbutton--following .followbutton__icon::before {
    content: "✓";
}

.followbutton.followbutton--hoverunfollow .followbutton__icon::before {
    content: "✕";
}


/* ---------- The compact follow toggle ----------
   Used on review cards, where the byline sits next to the avatar.
   Visually quiet — small text link with an icon. Works on desktop
   and mobile. */

.followtoggle {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    background: none;
    border: none;
    padding: 0.15rem 0.4rem;
    margin-top: 0.25rem;
    font-size: 0.75rem;
    font-weight: bold;
    color: var(--color-primary);
    cursor: pointer;
    border-radius: 0.25rem;
    text-decoration: none;
    font-family: inherit;
    transition: background 0.15s, color 0.15s;
}

.followtoggle:link,
.followtoggle:visited {
    color: var(--color-primary);
}

.followtoggle:hover {
    background: var(--color-background);
    text-decoration: none;
}

.followtoggle:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.followtoggle--following {
    color: var(--color-muted);
}

.followtoggle--following:link,
.followtoggle--following:visited {
    color: var(--color-muted);
}

.followtoggle--following:hover {
    color: #c00;
    background: #fff5f5;
}

.followtoggle__icon::before {
    content: "＋";
    font-weight: bold;
    font-size: 0.85rem;
    line-height: 1;
}

.followtoggle--following .followtoggle__icon::before {
    content: "✓";
}

.followtoggle--following:hover .followtoggle__icon::before {
    content: "✕";
}


/* ---------- Inline error tooltip near a follow button ----------
   Auto-dismisses after a few seconds. */

.followerror {
    display: inline-block;
    margin-left: 0.5rem;
    padding: 0.25rem 0.6rem;
    background: #fff5f5;
    color: #c00;
    border: 1px solid #f5c6c6;
    border-radius: 0.25rem;
    font-size: 0.8rem;
    font-weight: normal;
    vertical-align: middle;
}


/* ============================================================
   User profile page additions
   ============================================================ */

/* Counts row under the username — followers · following. */
.userprofile__counts {
    color: var(--color-muted);
    font-size: 0.875rem;
    margin-bottom: 0.5rem;
}

.userprofile__counts strong {
    color: var(--color-text);
    font-weight: bold;
}

/* Action row holding the follow button. */
.userprofile__actions {
    margin-top: 0.75rem;
}

/* "You've blocked this user" banner. */
.userprofile__blockednotice {
    background: #fff5f5;
    border: 1px solid #f5c6c6;
    color: #722;
    padding: 0.875rem 1rem;
    border-radius: 0.5rem;
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.userprofile__unblockbutton {
    background: #fff;
    color: #c00;
    border: 1px solid #c00;
    border-radius: 0.25rem;
    padding: 0.3rem 0.75rem;
    font-size: 0.85rem;
    font-weight: bold;
    cursor: pointer;
    font-family: inherit;
    margin-left: auto;
}

.userprofile__unblockbutton:hover {
    background: #c00;
    color: #fff;
}

/* Pagination links above and below the reviews list. */
.userprofile__pagenav {
    margin: 0.75rem 0;
    font-size: 0.9rem;
}

.userprofile__pagenav--bottom {
    text-align: right;
}

.userprofile__pagenav a {
    color: var(--color-primary);
    font-weight: bold;
}

.userprofile__pagenav a:hover {
    text-decoration: underline;
}

#hero {
	height: 250px;
	/*background: url(/images/lovebooks.webp);*/
	min-width: 18em;
	padding: 1em;
	border: var(--color-border) solid 1px;
	background-size: cover;
	border-radius: 1rem;
	margin-bottom: 1rem;
}

.icon {
    width: 1.5rem;
    height: 1.5rem;
    fill: currentColor;
	margin-right: 0.5em;
}

.socialmediaicon {
	float: left;
	padding: 0.25em;
}

.subscription {
	margin-top: 1rem; 
	text-align: center; 
	border: 1px solid #fbbed2; 
	background: rgb(255, 240, 255); 
	padding: 0.5em; 
	border-radius: 1rem;
}

.pendingemailnotice {
	border: 1px solid var(--color-secondary); 
	background: var(--color-background); 
	padding: 0.75em 1em; 
	margin-bottom: 1em;
}

/* ============================================================
   Sidebar profile box — REPLACE your existing .profilebox CSS
   with this section. Both variants below.
   ============================================================ */

.profilebox {
    width: 100%;
    border: 1px solid var(--color-border);
    border-radius: 1rem;
    background: var(--color-background);
    font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
    color: var(--color-text);
    margin-bottom: 1rem;
    overflow: hidden; /* clips the colored hero band to the rounded corners */
}

.profilebox a {
    text-decoration: none;
}

/* ============================================================
   Logged-out CTA variant
   ============================================================ */

.profilebox--cta {
    /* Reset; the hero/body sections handle their own padding. */
    padding: 0;
}

/* ----- Hero band (colored top section) ----- */

.profilebox__hero {
    /* Warm gradient — cream into a hint of the secondary orange.
       Reads as "golden hour", which is on-brand for a books site. */
    background: linear-gradient(
        135deg,
        #fff7eb 0%,
        #ffe9c9 60%,
        #f9d59a 100%
    );
    padding: 1.25rem 1rem 0.75rem 1rem;
    text-align: center;
    position: relative;
    overflow: hidden;
}

/* Subtle decorative texture — a couple of pale circles in the corners
   for depth, like soft light flares. Pure decoration, no semantic
   meaning. */
.profilebox__hero::before {
    content: "";
    position: absolute;
    top: -2rem;
    right: -2rem;
    width: 5rem;
    height: 5rem;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.4);
    pointer-events: none;
}

.profilebox__hero::after {
    content: "";
    position: absolute;
    bottom: -1.5rem;
    left: -1.5rem;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.25);
    pointer-events: none;
}

/* "Free to join" pill — small badge in the top-right of the hero. */
.profilebox__pill {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    background: #fff;
    color: var(--color-primary);
    font-size: 0.65rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.2rem 0.55rem;
    border-radius: 1rem;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
    z-index: 1;
}

/* Multi-book illustration, sized to hero. Subtle drop-shadow gives
   the books a tiny bit of weight against the warm background. */
.profilebox__books {
    width: 7rem;
    height: auto;
    max-width: 100%;
    display: block;
    margin: 0 auto;
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.12));
    position: relative;
    z-index: 0;
}

/* ----- Body (white content section) ----- */

.profilebox__body {
    padding: 1.25rem 1.25rem 1.25rem 1.25rem;
    text-align: center;
}

.profilebox__headline {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.35rem;
    line-height: 1.25;
    color: var(--color-primary);
    margin: 0 0 1rem 0;
    font-weight: normal;
}

.profilebox__headline em {
    color: var(--color-secondary);
    font-style: italic;
    font-weight: normal;
}

.profilebox__benefits {
    list-style: none;
    padding: 0;
    margin: 0 0 1.25rem 0;
    text-align: left;
}

.profilebox__benefits li {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    margin: 0 0 0.5rem 0;
    margin-inline-start: 0; /* override the global li indent */
    font-size: 0.825rem;
    color: var(--color-text);
    line-height: 1.4;
}

.profilebox__benefits li:last-child {
    margin-bottom: 0;
}

.profilebox__benefits svg {
    width: 1rem;
    height: 1rem;
    flex-shrink: 0;
    color: var(--color-secondary);
    margin-top: 0.15rem;
}

/* CTA button — slightly raised on hover for a tiny lift effect. */
.profilebox__cta {
    display: block;
    background: var(--color-primary);
    color: #fff;
    border: 1px solid var(--color-primary);
    border-radius: 0.5rem;
    padding: 0.7rem 1rem;
    font-size: 0.95rem;
    font-weight: bold;
    text-align: center;
    cursor: pointer;
    margin-bottom: 0.75rem;
    transition: background 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.15s;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.profilebox__cta:link,
.profilebox__cta:visited {
    color: #fff;
}

.profilebox__cta:hover {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
    text-decoration: none;
    transform: translateY(-1px);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.profilebox__cta:active {
    transform: translateY(0);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.profilebox__altaction {
    margin: 0;
    font-size: 0.8rem;
    color: var(--color-muted);
}

.profilebox__altactionlink {
    font-weight: bold;
    margin-left: 0.15rem;
}

.profilebox__altactionlink:link,
.profilebox__altactionlink:visited {
    color: var(--color-primary);
}

.profilebox__altactionlink:hover {
    text-decoration: underline;
}

/* ============================================================
   Logged-in account variant
   ============================================================ */

.profilebox--loggedin {
    padding: 1.5rem 1.25rem;
    text-align: center;
}

.profilebox__avatarlink {
    display: inline-block;
    margin-bottom: 0.75rem;
    transition: transform 0.15s;
}

.profilebox__avatarlink:hover {
    transform: scale(1.03);
}

.profilebox__avatar {
    width: 6rem;
    height: 6rem;
    object-fit: cover;
    border-radius: 50%;
    border: 1px solid var(--color-border);
    background: var(--color-background);
    display: block;
}

.profilebox__namelink {
    display: block;
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.1rem;
    color: var(--color-primary);
    margin-bottom: 0.4rem;
    word-break: break-word;
}

.profilebox__namelink:hover {
    text-decoration: underline;
}

/* Decorative accent line below the username — short, primary colour. */
.profilebox__nameaccent {
    display: block;
    width: 2.5rem;
    height: 2px;
    background: var(--color-secondary);
    margin: 0 auto 0.5rem auto;
    border-radius: 1px;
}

.profilebox__memberline {
    font-size: 0.75rem;
    color: var(--color-muted);
    margin-bottom: 0.5rem;
    font-style: italic;
}

.profilebox__publiclink {
    display: block;
    font-size: 0.8rem;
    color: var(--color-muted);
    margin-bottom: 1rem;
}

.profilebox__publiclink:link,
.profilebox__publiclink:visited {
    color: var(--color-muted);
}

.profilebox__publiclink:hover {
    color: var(--color-primary);
}

.profilebox__booklistwrap {
    display: block;
}

/* ============================================================
   Reviews — append to your existing stylesheet
   ============================================================ */

/* The "Write a review" entry button — matches the share/favorite
   button styling for visual consistency with the rest of the page. */
.reviewopenbutton {
    margin-top: 0.5rem;
    margin-bottom: 1rem;
    background: var(--color-background);
    color: var(--color-primary);
    padding: 0.5rem 1rem;
    border: 1px solid var(--color-primary);
    border-radius: 0.5em;
    font-size: 0.875rem;
    cursor: pointer;
    font-family: inherit;
}

.reviewopenbutton:hover {
    background: var(--color-primary);
    color: #fff;
}

/* The review write/edit form. */
.reviewform {
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    padding: 1rem;
    margin-bottom: 1rem;
    /* When auto-scrolled into view (?action=write/edit-mine), leave
       a visual gap above the form so it doesn't hug the viewport's
       top edge. scrollIntoView({block:'start'}) honours this margin. */
    scroll-margin-top: 1rem;
}

.reviewform__starsrow {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.reviewform__starsrow label {
    font-size: 0.875rem;
    font-weight: normal;
    color: var(--color-muted);
}

.reviewform__stars {
    display: inline-flex;
    gap: 0.25rem;
    cursor: pointer;
    user-select: none;
    font-size: 1.5rem;
    line-height: 1;
}

.reviewform__stars .star {
    color: var(--color-muted);
    cursor: pointer;
    padding: 0 0.1rem;
}

.reviewform__stars .star:hover,
.reviewform__stars .star--filled {
    color: var(--color-secondary);
}

.reviewform__body {
    width: 100%;
    min-height: 8rem;
    padding: 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: 0.25rem;
    font-family: inherit;
    font-size: 1rem;
    color: var(--color-text);
    resize: vertical;
    box-sizing: border-box;
}

.charcount {
    text-align: right;
    font-size: 0.75rem;
    color: var(--color-muted);
    margin-top: 0.25rem;
}

.charcount--over {
    color: #c00;
    font-weight: bold;
}

.reviewform__buttons {
    margin-top: 0.75rem;
    display: flex;
    gap: 0.5rem;
}

.reviewform__buttons button {
    padding: 0.5rem 1rem;
    border-radius: 0.5em;
    font-size: 0.875rem;
    cursor: pointer;
    font-family: inherit;
}

#reviewsubmitbutton {
    background: var(--color-primary);
    color: #fff;
    border: 1px solid var(--color-primary);
}

#reviewsubmitbutton:hover {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
}

#reviewsubmitbutton:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

#reviewcancelbutton {
    background: #fff;
    color: var(--color-muted);
    border: 1px solid var(--color-border);
}

#reviewcancelbutton:hover {
    background: var(--color-background);
}

/* Rendered reviews — extending your existing .bookreview styles. */
.review-list {
    margin-top: 1rem;
}

.bookreview {
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    padding: 1rem;
    margin-bottom: 0.5rem;
}

.bookreviewdetail {
    display: flex;
    gap: 1rem;
}

.bookreviewusername {
    flex: 0 0 auto;
    width: 4rem;
    text-align: center;
    font-size: 0.75rem;
    color: var(--color-muted);
}

.bookreviewusername img {
    width: 3rem;
    height: 3rem;
    object-fit: cover;
    border-radius: 50%;
    border: 1px solid var(--color-border);
}

.bookreviewbody {
    flex: 1;
    min-width: 0; /* prevents flex item overflow on long words */
}

.bookreview__rating {
    color: var(--color-secondary);
    font-size: 1rem;
    line-height: 1;
}

.bookreview__rating .star {
    color: var(--color-border);
}

.bookreview__rating .star--filled {
    color: var(--color-secondary);
}

.bookreview__date {
    font-size: 0.75rem;
    color: var(--color-muted);
    margin-top: 0.25rem;
    margin-bottom: 0.5rem;
}

.bookreview__edited {
    font-style: italic;
}

.bookreview__text {
    word-wrap: break-word;
    line-height: 1.5;
}

.bookreview__actions {
    margin-top: 0.5rem;
    display: flex;
    gap: 0.5rem;
}

.bookreview__actions button {
    padding: 0.25rem 0.75rem;
    background: #fff;
    color: var(--color-muted);
    border: 1px solid var(--color-border);
    border-radius: 0.25rem;
    font-size: 0.75rem;
    cursor: pointer;
    font-family: inherit;
}

.bookreview__actions button:hover {
    background: var(--color-background);
    color: var(--color-text);
}

.bookreview__actions .reviewdelete:hover {
    border-color: #c00;
    color: #c00;
}

/* ============================================================
   User profile pages — append to your existing stylesheet
   ============================================================ */

.userprofile {
    background: #fff;
    border-radius: 1rem;
    padding: 1.5rem;
    margin-top: 1rem;
}

.userprofile__header {
    display: flex;
    gap: 1.5rem;
    align-items: flex-start;
    margin-bottom: 1.5rem;
}

.userprofile__avatar {
    width: 6rem;
    height: 6rem;
    object-fit: cover;
    border-radius: 50%;
    border: 1px solid var(--color-border);
    flex: 0 0 auto;
}

.userprofile__meta {
    flex: 1;
    min-width: 0;
}

.userprofile__username {
    margin: 0 0 0.25rem 0;
}

.userprofile__memberSince {
    color: var(--color-muted);
    font-size: 0.875rem;
    margin-bottom: 0.5rem;
}

.userprofile__bio {
    line-height: 1.5;
    color: var(--color-text);
    margin-top: 0.5rem;
}

.userprofile__stats {
    display: flex;
    gap: 2rem;
    padding: 1rem 0;
    border-top: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-border);
    margin-bottom: 1rem;
}

.userprofile__stat {
    text-align: center;
}

.userprofile__statvalue {
    font-size: 1.5rem;
    font-weight: bold;
    color: var(--color-primary);
}

.userprofile__statlabel {
    font-size: 0.75rem;
    color: var(--color-muted);
    text-transform: uppercase;
}

.userprofile__reviews {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.userprofile__more {
    color: var(--color-muted);
    font-size: 0.875rem;
    margin-top: 1rem;
    text-align: center;
}

/* A review block as it appears on the user profile — book on the left,
   review content on the right. Mirrors the .bookreview structure but
   with book context instead of user context. */
.userprofilereview {
    display: flex;
    gap: 1rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    padding: 1rem;
    border-bottom: 2px solid var(--color-tertiary);
}

.userprofilereview__cover {
    flex: 0 0 auto;
    width: 4rem;
}

.userprofilereview__cover img {
    width: 100%;
    height: auto;
    border-radius: 0.25rem;
    border: 1px solid var(--color-border);
}

.userprofilereview__body {
    flex: 1;
    min-width: 0;
}

.userprofilereview__book {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-weight: bold;
    margin-bottom: 0.25rem;
}

.userprofilereview__author {
    color: var(--color-muted);
    font-size: 0.875rem;
    font-weight: normal;
    font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
}

.userprofilereview__kicker {
    display: inline-block;
    font-size: 0.65rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-tertiary);
    margin-bottom: 0.25rem;
}

.userprofilereview__readmore {
    display: inline-block;
    font-size: 0.8rem;
    font-weight: bold;
    color: var(--color-primary);
    margin-top: 0.5rem;
}

.userprofilereview__readmore:hover {
    text-decoration: underline;
}

/* Bio textarea on /profile/index.php */
.biofield {
    width: 100%;
    min-height: 5rem;
    padding: 0.75em;
    border: 1px solid var(--color-border);
    border-radius: 0.25em;
    font-family: inherit;
    font-size: 1em;
    color: var(--color-text);
    resize: vertical;
    box-sizing: border-box;
}

/* ============================================================
   Profile page layout — append to your existing stylesheet
   ============================================================ */

.profilepage {
    margin-bottom: 6rem; /* breathing room above the sticky save bar */
}

.profilepage__title {
    margin-bottom: 1.5rem;
}

.profilepage__layout {
    display: grid;
    grid-template-columns: 18rem 1fr;
    gap: 1.5rem;
    align-items: start;
}

/* ----- Sidebar ----- */
.profilepage__sidebar {
    background: #fff;
    border-radius: 1rem;
    padding: 1.5rem;
    text-align: center;
    position: sticky;
    top: 1rem;
	border-bottom: 1px solid var(--color-muted);
}

.profilepage__avatar {
    width: 9rem;
    height: 9rem;
    margin: 0 auto 1rem auto;
    border-radius: 50%;
    overflow: hidden;
    border: 1px solid var(--color-border);
    background: var(--color-background);
}

.profilepage__avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.profilepage__identity {
    margin-bottom: 1rem;
}

.profilepage__username {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.25rem;
    font-weight: bold;
    color: var(--color-primary);
    margin-bottom: 0.25rem;
    word-break: break-word;
}

.profilepage__publiclink {
    font-size: 0.875rem;
    color: var(--color-muted);
}

.profilepage__upload {
    margin: 1rem 0;
}

/* uploadifive renders the trigger as a div with our buttonClass on it
   AND its own `.uploadifive-button` class. The compound selector below
   (.uploadifive-button.profilepicchange) has higher specificity than
   either class alone, so it wins regardless of whether uploadifive.css
   or style.css loads last.

   We also need to set cursor on the hidden file <input> uploadifive
   layers on top of the button — that's the element actually under the
   pointer when the user hovers. */
.uploadifive-button.profilepicchange,
.profilepicchange {
    display: inline-block;
    width: 100%;
    background: var(--color-background);
    color: var(--color-primary);
    border: 1px solid var(--color-primary);
    border-radius: 0.5em;
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
    cursor: pointer;
    text-align: center;
    font-family: inherit;
}

.uploadifive-button.profilepicchange:hover,
.profilepicchange:hover {
    background: var(--color-primary-light);
    color: var(--color-primary);
    border-color: var(--color-primary);
}

/* The file input uploadifive overlays on top of the button needs its
   own cursor or the pointer reverts to the browser default for file
   inputs (often arrow or text). */
.uploadifive-button.profilepicchange input,
.profilepicchange input[type="file"] {
    cursor: pointer;
}

/* "Use my owl avatar" — sits below the Change picture button and shares
   its dimensions, but uses a quieter grey-on-cream styling so it reads
   as a secondary action paired with the primary upload. */
.profilepage__revertowl {
    display: inline-block;
    width: 100%;
    margin-top: 0.5rem;
    background: var(--color-background);
    color: var(--color-muted);
    border: 1px solid var(--color-border);
    border-radius: 0.5em;
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
    cursor: pointer;
    text-align: center;
    font-family: inherit;
}

.profilepage__revertowl:hover {
    background: var(--color-primary-light);
    color: var(--color-primary);
    border-color: var(--color-primary);
}

.profilepage__revertowl[hidden] {
    /* Belt-and-braces: the `hidden` attribute should hide it already,
       but some legacy CSS resets override that behaviour. */
    display: none;
}

/* ---- Revert-to-owl confirmation dialog ----
   Native <dialog> element. Browser defaults are ugly; we style the box
   to match the rest of the site (rounded corners, soft background,
   the project's button language for the two actions). */
.revertowldialog {
    border: 1px solid var(--color-border);
    border-radius: 0.5em;
    padding: 1.5rem;
    max-width: 28rem;
    width: calc(100% - 2rem);
    background: #fff;
    color: var(--color-text);
    font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}

.revertowldialog::backdrop {
    background: rgba(0, 0, 0, 0.45);
}

.revertowldialog__title {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.25rem;
    font-weight: bold;
    color: var(--color-primary);
    margin: 0 0 0.75rem 0;
}

.revertowldialog__body {
    font-size: 0.95rem;
    line-height: 1.45;
    color: var(--color-text);
    margin: 0 0 1rem 0;
}

.revertowldialog__error {
    /* Inherits .errormessage from the rendered HTML; we just tighten
       the spacing so it sits nicely above the action row. */
    padding-bottom: 0;
    margin-bottom: 0.75rem;
    min-height: 1.25rem;
}

.revertowldialog__actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 0.5rem;
}

.revertowldialog__cancel,
.revertowldialog__confirm {
    border-radius: 0.5em;
    padding: 0.5rem 1.25rem;
    font-size: 0.95rem;
    cursor: pointer;
    font-family: inherit;
    border: 1px solid var(--color-border);
}

.revertowldialog__cancel {
    background: #fff;
    color: var(--color-muted);
}

.revertowldialog__cancel:hover {
    background: var(--color-background);
    color: var(--color-text);
}

.revertowldialog__confirm {
    background: var(--color-primary);
    color: #fff;
    border-color: var(--color-primary);
    font-weight: bold;
}

.revertowldialog__confirm:hover {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
}

.revertowldialog__confirm:disabled {
    background: var(--color-muted-light);
    border-color: var(--color-muted-light);
    cursor: not-allowed;
}

.profilepage__logoutform {
    margin-top: 1.5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--color-border);
}

.profilepage__logoutbutton {
    width: 100%;
    background: #fff;
    color: var(--color-muted);
    border: 1px solid var(--color-border);
    border-radius: 0.5em;
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
    cursor: pointer;
    font-family: inherit;
}

.profilepage__logoutbutton:hover {
    background: var(--color-background);
    color: var(--color-text);
}

/* ----- Main column / cards ----- */
.profilepage__main {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    min-width: 0; /* prevent grid blowout when card content is wide */
}

.profilecard {
    background: #fff;
    border-radius: 1rem;
    padding: 1.5rem;
	margin-bottom: 1.5rem;
	border-bottom: 1px solid var(--color-muted);
}

.profilecard__title {
    margin: 0 0 1rem 0;
    font-size: 1.125rem;
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    color: var(--color-primary);
}

.profilecard__field {
    margin-bottom: 1rem;
}

.profilecard__field:last-child {
    margin-bottom: 0;
}

.profilecard__field label {
    display: block;
    margin-bottom: 0.25rem;
}

.profilecard__field input[type="text"],
.profilecard__field input[type="email"],
.profilecard__field input[type="password"] {
    width: 100%;
    max-width: 30rem;
}

.profilecard__help {
    font-size: 0.875rem;
    color: var(--color-muted);
    margin: 0 0 0.5rem 0;
    line-height: 1.4;
}

.profilecard__checkbox {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: normal;
    cursor: pointer;
}

/* Genre checkbox grid — fits 2-3 columns on desktop, 1 on narrow widths. */
.profilecard__genres {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
    gap: 0.5rem;
    margin-top: 0.5rem;
}

.profilecard__genre {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: normal;
    cursor: pointer;
    padding: 0.25rem 0;
}

/* ----- Sticky save bar ----- */
.profilesavebar {
    position: sticky;
    bottom: 0;
    margin-top: 2rem;
    margin-left: -1rem;
    margin-right: -1rem;
    padding: 0.75rem 1rem;
    background: #fff;
    border-top: 1px solid var(--color-border);
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
    display: flex;
    justify-content: flex-end;
    z-index: 10;
}

.profilesavebar__button {
    background: var(--color-primary);
    color: #fff;
    border: 1px solid var(--color-primary);
    border-radius: 0.5em;
    padding: 0.625rem 1.5rem;
    font-size: 0.95rem;
    font-weight: bold;
    cursor: pointer;
    font-family: inherit;
    min-width: 10rem;
}

.profilesavebar__button:hover {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
}

/* The right hamburger uses a person silhouette SVG instead of the
   three-bar hamburger, since its drawer holds the user's profile and
   booklists rather than navigation. The .hamburger and .hamburger-right
   rules already in your stylesheet handle positioning, visibility, and
   the breakpoint behaviour — these rules just override the inner
   layout to render an icon. */
.hamburger-profile {
    /* Override the column flex layout from .hamburger (which arranged
       three bars vertically). For an SVG icon we want it centered. */
    flex-direction: row;
    gap: 0;
    color: var(--color-muted);
    padding: 0;
}

.hamburger-profile svg {
    width: 24px;
    height: 24px;
}

/* When the user is logged in, tint the icon in the site's primary
   colour so it reads as "your account" rather than "log in". A subtle
   visual cue that contrasts with the muted, generic look when logged
   out. */
.hamburger-profile--loggedin {
    color: var(--color-primary);
}

.hamburger-profile:hover {
    color: var(--color-primary);
    background: var(--color-background);
}

/* The container — centers the card horizontally and gives it
   breathing room on desktop. */
.authpage {
    display: flex;
    justify-content: center;
    padding: 2rem 1rem;
}

/* The card itself — narrow, focused, centered. */
.authcard {
    width: 100%;
    max-width: 25rem;
    background: #fff;
    border-radius: 1rem;
    padding: 2rem;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
}

.authcard__greeting {
    color: var(--color-muted);
    font-size: 0.95rem;
    margin: 0 0 0.25rem 0;
}

.authcard__title {
    margin: 0 0 1.5rem 0;
    font-size: 1.75rem;
}

.authcard__notice {
    background: var(--color-background);
    border: 1px solid var(--color-secondary);
    border-radius: 0.5rem;
    padding: 0.75rem 1rem;
    margin-bottom: 1.5rem;
    font-size: 0.9rem;
    line-height: 1.4;
}

/* The form itself — vertical stack with consistent spacing. */
.authform__field {
    margin-bottom: 1rem;
}

.authform__field label {
    display: block;
    margin-bottom: 0.25rem;
    font-size: 0.875rem;
}

.authform__field input {
    width: 100%;
}

/* Forgot password — small, right-aligned under the password input.
   Tertiary action, deliberately unobtrusive. */
.authform__forgot {
    display: block;
    text-align: right;
    margin-top: 0.25rem;
    font-size: 0.8rem;
    color: var(--color-muted);
}

.authform__forgot:link,
.authform__forgot:visited {
    color: var(--color-muted);
}

.authform__forgot:hover {
    color: var(--color-primary);
}

.authform__error {
    margin: 0.5rem 0;
    min-height: 1.5rem;
}

/* Primary submit button — full-width, brand colour. */
.authform__submit {
    width: 100%;
    background: var(--color-primary);
    color: #fff;
    border: 1px solid var(--color-primary);
    border-radius: 0.5em;
    padding: 0.75rem 1rem;
    font-size: 1rem;
    font-weight: bold;
    cursor: pointer;
    font-family: inherit;
    margin-top: 0.5rem;
}

.authform__submit:hover {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
}

.authform__submit:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* Footer — separator line then a prominent secondary action.
   The "Create an account" link is the page's secondary CTA, so it gets
   its own visually distinct block under a divider — deliberate
   separation from the primary login flow above. */
.authcard__footer {
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--color-border);
    text-align: center;
    font-size: 0.95rem;
    color: var(--color-muted);
}

.authcard__footerlink {
    font-weight: bold;
    margin-left: 0.25rem;
}

.authcard__footerlink:link,
.authcard__footerlink:visited {
    color: var(--color-primary);
}

.authcard__footerlink:hover {
    text-decoration: underline;
}

/* Wider variant of the auth card, for forms with more content
   (signup needs room for genre grid, name pair, etc.) */
.authcard--wide {
    max-width: 32rem;
}
 
/* Body text inside auth cards — used by forgot.php for the
   "check your email" and expired-link states, and by signup.php
   for the welcome blurb. */
.authcard__body {
    color: var(--color-text);
    line-height: 1.5;
    margin: 0 0 1rem 0;
}
 
.authcard__body:last-child {
    margin-bottom: 0;
}

/* Top-of-card "already have an account?" prompt. The signup form is
   long, so this surfaces the login link near the top for users who
   would otherwise have to scroll to the footer to find it. Mirrors
   the footer prompt's wording and reuses .authcard__footerlink for
   the anchor styling. */
.authcard__loginprompt {
    margin: 0 0 1.5rem 0;
    font-size: 0.95rem;
    color: var(--color-muted);
}
 
/* Form groups — visually segment the long signup form into
   coherent sections (credentials / personal details / preferences). */
.authform__group {
    margin-bottom: 1.5rem;
    padding-bottom: 1.5rem;
    border-bottom: 1px solid var(--color-border);
}
 
.authform__group:last-of-type {
    margin-bottom: 1rem;
    padding-bottom: 0;
    border-bottom: none;
}
 
.authform__grouptitle {
    font-size: 1rem;
    margin: 0 0 0.25rem 0;
    color: var(--color-primary);
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
}
 
.authform__grouphelp {
    font-size: 0.875rem;
    color: var(--color-muted);
    margin: 0 0 1rem 0;
    line-height: 1.4;
}
 
.authform__help {
    font-size: 0.8rem;
    color: var(--color-muted);
    margin: 0 0 0.25rem 0;
    line-height: 1.4;
}
 
/* Inline errors below a single field — tighter than the
   form-level error block. */
.authform__inline-error {
    font-size: 0.85rem;
    margin-top: 0.25rem;
    min-height: 1.25rem;
    padding-bottom: 0;
}
 
/* First name / last name as side-by-side on desktop, stacked on mobile. */
.authform__field-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}


/* Genre checkbox grid — same `auto-fill` pattern as the profile
   page so genres flow naturally into 1-2 columns based on width. */
.authform__genres {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: 0.5rem;
}
 
.authform__genre {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: normal;
    font-size: 0.9rem;
    cursor: pointer;
    padding: 0.25rem 0;
}
 
/* The big "Subscribe" checkbox — needs more emphasis than a
   regular field since it's the only opt-in toggle on the page. */
.authform__checkbox {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    cursor: pointer;
    font-weight: normal;
    background: var(--color-background);
    padding: 0.75rem 1rem;
    border-radius: 0.5rem;
}
 
.authform__checkbox input[type="checkbox"] {
    margin-top: 0.2rem;
    flex-shrink: 0;
}
 
.authform__checkbox > span {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
 
.authform__checkboxhelp {
    font-size: 0.8rem;
    color: var(--color-muted);
    font-weight: normal;
    line-height: 1.4;
}

.authform__genres {
    grid-template-columns: 1fr;
}

/* The generic error slot inside the sticky save bar.
   Sits to the LEFT of the Save button on desktop, above it on mobile.
   Uses flex's auto-margin trick to push the button to the right
   while letting the error take whatever space it needs. */
.profilesavebar__error {
    margin: 0;
    padding: 0;
    align-self: center;
    text-align: right;
    flex: 1;
    min-width: 0; /* allow truncation if needed */
    margin-right: 1rem;
}

/* ============================================================
   Mobile signup banner — append to your stylesheet
   ============================================================ */

/* Hidden by default — shown only at mobile widths via the
 (max-width: 640px) block at the bottom. */
.mobilesignupbanner {
    display: none;
}

.mobilesignupbanner__sparkle {
    margin-right: 0.4rem;
}

/* ============================================================
   Homepage layout
   ============================================================ */

.home {
    /* Each homepage section gets its own padding, so the wrapper
       stays minimal. The negative margins line the hero up flush
       with the content area's edges. */
}

.home__sectiontitle {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    color: var(--color-primary);
    margin-bottom: 0.5rem;
}

.home__sectionsub {
    color: var(--color-muted);
    margin-bottom: 1.5rem;
}

/* ----- Shared button styling on the homepage ----- */

.home__btn {
    display: inline-block;
    padding: 0.6rem 1.25rem;
    border-radius: 0.5rem;
    font-size: 0.95rem;
    font-weight: bold;
    cursor: pointer;
    border: 1px solid transparent;
    text-align: center;
    transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.15s, box-shadow 0.15s;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.home__btn--lg {
    padding: 0.85rem 1.75rem;
    font-size: 1.05rem;
}

.home__btn--primary {
    background: var(--color-primary);
    color: #fff;
    border-color: var(--color-primary);
}

.home__btn--primary:link,
.home__btn--primary:visited {
    color: #fff;
}

.home__btn--primary:hover {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
    text-decoration: none;
    transform: translateY(-1px);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.home__btn--secondary {
    background: #fff;
    color: var(--color-primary);
    border-color: var(--color-primary);
}

.home__btn--secondary:hover {
    background: var(--color-primary);
    color: #fff;
    text-decoration: none;
}

.home__btn--ghost {
    background: transparent;
    color: var(--color-primary);
    border-color: transparent;
    box-shadow: none;
}

.home__btn--ghost:hover {
    background: rgba(255, 255, 255, 0.4);
    text-decoration: none;
}

/* ============================================================
   Logged-in welcome
   ============================================================ */

.home__welcome {
    background: #fff;
    border-radius: 1rem;
    padding: 2rem;
    margin-bottom: 1.5rem;
}

.home__welcometitle {
    margin-bottom: 0.5rem;
}

.home__welcomelead {
    color: var(--color-muted);
    margin-bottom: 1.5rem;
    font-size: 1.05rem;
}

.home__welcomeactions {
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
}

/* ============================================================
   Hero (logged-out)
   ============================================================ */

.home__hero {
    background: linear-gradient(
        135deg,
        #fff7eb 0%,
        #ffe9c9 60%,
        #f9d59a 100%
    );
    border-radius: 1rem;
    margin-bottom: 1.5rem;
    overflow: hidden;
    position: relative;
}

/* Same decorative light flares as the sidebar profilebox, scaled up. */
.home__hero::before {
    content: "";
    position: absolute;
    top: -3rem;
    right: -3rem;
    width: 10rem;
    height: 10rem;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.4);
    pointer-events: none;
}

.home__hero::after {
    content: "";
    position: absolute;
    bottom: -2rem;
    left: -2rem;
    width: 7rem;
    height: 7rem;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.25);
    pointer-events: none;
}

.home__heroinner {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 2rem;
    align-items: center;
    padding: 2.5rem;
    position: relative; /* sit above the ::before/::after decoration */
    z-index: 1;
}

.home__herotext {
    min-width: 0;
}

.home__herokicker {
    color: var(--color-secondary);
    font-size: 0.85rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 0.5rem;
}

.home__herotitle {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 2.5rem;
    line-height: 1.15;
    color: var(--color-primary);
    margin-bottom: 1rem;
    font-weight: normal;
}

.home__herotitle em {
    color: var(--color-secondary);
    font-style: italic;
    font-weight: normal;
}

.home__herolead {
    font-size: 1.05rem;
    color: var(--color-text);
    margin-bottom: 1.5rem;
    max-width: 32rem;
    line-height: 1.5;
}

.home__heroactions {
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.home__heroart {
    color: var(--color-primary);
    flex-shrink: 0;
}

.home__heroart svg {
    width: 12rem;
    height: auto;
    filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.15));
}

/* ============================================================
   Benefits row (logged-out)
   ============================================================ */

.home__benefits {
    background: #fff;
    border-radius: 1rem;
    padding: 2rem;
    margin-bottom: 1.5rem;
    text-align: center;
}

.home__benefitsgrid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1.5rem;
    margin-top: 1rem;
}

.home__benefit {
    text-align: center;
}

.home__benefiticon {
    width: 3rem;
    height: 3rem;
    margin: 0 auto 0.75rem auto;
    color: var(--color-secondary);
    background: var(--color-background);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.home__benefiticon svg {
    width: 1.5rem;
    height: 1.5rem;
}

.home__benefittitle {
    font-size: 1.05rem;
    margin-bottom: 0.5rem;
    color: var(--color-primary);
}

.home__benefittext {
    color: var(--color-muted);
    font-size: 0.9rem;
    line-height: 1.5;
}

/* ============================================================
   Recent reviews
   ============================================================ */

.home__reviews {
    background: #fff;
    border-radius: 1rem;
    padding: 2rem;
    margin-bottom: 1.5rem;
}

.home__reviewsgrid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
    gap: 1rem;
}

.reviewcard {
    display: flex;
    gap: 0.75rem;
    background: var(--color-background);
    border-radius: 0.75rem;
    padding: 1rem;
    transition: transform 0.15s, box-shadow 0.15s;
}

.reviewcard:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.06);
}

.reviewcard__cover {
    flex-shrink: 0;
    width: 4.5rem;
}

.reviewcard__cover img {
    width: 100%;
    height: auto;
    border-radius: 0.25rem;
    border: 1px solid var(--color-border);
    display: block;
}

.reviewcard__body {
    flex: 1;
    min-width: 0;
}

.reviewcard__title {
    display: block;
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-weight: bold;
    color: var(--color-primary);
    margin-bottom: 0.15rem;
    line-height: 1.25;
    word-break: break-word;
}

.reviewcard__author {
    color: var(--color-muted);
    font-size: 0.8rem;
    margin-bottom: 0.4rem;
}

.reviewcard__rating {
    color: var(--color-secondary);
    font-size: 0.9rem;
    line-height: 1;
    margin-bottom: 0.4rem;
}

.reviewcard__excerpt {
    font-size: 0.85rem;
    line-height: 1.5;
    color: var(--color-text);
    margin-bottom: 0.5rem;
    /* Allow up to 4 lines, then ellipsize. Webkit-only but
       degrades gracefully — non-webkit browsers will just see
       the full text or our PHP-side 220-char clip. */
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.reviewcard__byline {
    font-size: 0.75rem;
    color: var(--color-muted);
}

.reviewcard__byline a {
    color: var(--color-primary);
    font-weight: bold;
}

.reviewcard__byline a:hover {
    text-decoration: underline;
}

/* ============================================================
   Trending Now (logged-out homepage)

   Sits between hero and benefits. Cover-led cards in a 4-up
   grid — visually punchier than the side-by-side reviewcard
   layout, which suits a discovery surface near the fold.

   Visual language matches the other home__ sections: white
   rounded container, primary-color heading, muted subtitle,
   subtle lift on hover.
   ============================================================ */

.home__trending {
    background: #fff;
    border-radius: 1rem;
    padding: 2rem;
    margin-bottom: 1.5rem;
}

.home__trendinggrid {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 1.5rem;
    margin-top: 1rem;
}

.trendingcard {
    display: block;
    color: inherit;
    text-decoration: none;
    transition: transform 0.15s, box-shadow 0.15s;
    border-radius: 0.5rem;
}

.trendingcard:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.06);
}

.trendingcard__cover {
    aspect-ratio: 2 / 3;
    overflow: hidden;
    border-radius: 0.4rem;
    border: 1px solid var(--color-border);
    background: var(--color-background);
}

.trendingcard__cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.trendingcard__body {
    margin-top: 0.6rem;
    padding: 0 0.1rem;
}

.trendingcard__title {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-weight: bold;
    color: var(--color-primary);
    font-size: 0.9rem;
    line-height: 1.3;
    margin-bottom: 0.15rem;
    word-break: break-word;
    /* Three-line clamp — NYT titles get long ("The Light We
       Carry: Overcoming in Uncertain Times"). Three lines is
       enough headroom without making cards inconsistent. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.trendingcard__author {
    color: var(--color-muted);
    font-size: 0.8rem;
    /* One-line clamp on author. */
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ============================================================
   Bottom CTA
   ============================================================ */

.home__bottomcta {
    background: linear-gradient(
        135deg,
        var(--color-primary) 0%,
        #1c3d2f 100%
    );
    color: #fff;
    border-radius: 1rem;
    padding: 3rem 2rem;
    text-align: center;
    margin-bottom: 1.5rem;
    position: relative;
    overflow: hidden;
}

/* Subtle decorative book-page texture using diagonal lines.
   Pure decoration. */
.home__bottomcta::before {
    content: "";
    position: absolute;
    top: -2rem;
    right: -2rem;
    width: 12rem;
    height: 12rem;
    border-radius: 50%;
    background: rgba(229, 161, 93, 0.15);
    pointer-events: none;
}

.home__bottomtitle {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    color: #fff;
    font-size: 1.75rem;
    margin-bottom: 0.5rem;
    position: relative;
    z-index: 1;
}

.home__bottomlead {
    color: rgba(255, 255, 255, 0.9);
    font-size: 1.05rem;
    margin-bottom: 1.5rem;
    position: relative;
    z-index: 1;
}

.home__bottomcta .home__btn {
    position: relative;
    z-index: 1;
}

/* Override primary button hover inside the bottom CTA — secondary
   colour pops against the dark green background. */
.home__bottomcta .home__btn--primary {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
}

.home__bottomcta .home__btn--primary:hover {
    background: #fff;
    color: var(--color-primary);
    border-color: #fff;
}

/* ============================================================
   Homepage feed — append to your stylesheet
   ============================================================ */

/* ---------- Compact welcome header ----------
   Smaller than the previous welcome card. One headline + one link. */

.home__welcomesmall {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
    padding: 0.5rem 0.25rem;
}

.home__welcomesmalltitle {
    font-size: 1.5rem;
    margin: 0;
    color: var(--color-primary);
}

.home__welcomesmalllink {
    font-size: 0.9rem;
    color: var(--color-muted);
}

.home__welcomesmalllink:link,
.home__welcomesmalllink:visited {
    color: var(--color-muted);
}

.home__welcomesmalllink:hover {
    color: var(--color-primary);
}

/* ---------- Feed container ---------- */

.home__feed {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.home__pagenav {
    margin: 0.5rem 0;
    font-size: 0.9rem;
}

.home__pagenav--bottom {
    text-align: right;
    margin-top: 1rem;
}

.home__pagenav a {
    color: var(--color-primary);
    font-weight: bold;
}

/* ---------- Feed cards (shared base) ---------- */

.feedcard {
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.75rem;
    padding: 1rem;
}

.feedcard__head {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    margin-bottom: 0.75rem;
}

.feedcard__avatar {
    flex-shrink: 0;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    overflow: hidden;
    border: 1px solid var(--color-border);
    background: var(--color-background);
    display: block;
}

.feedcard__avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.feedcard__avatar--small {
    width: 2rem;
    height: 2rem;
}

.feedcard__headtext {
    flex: 1;
    min-width: 0;
}

.feedcard__line {
    font-size: 0.95rem;
    line-height: 1.4;
}

.feedcard__user {
    color: var(--color-primary);
    font-weight: bold;
}

.feedcard__user:hover {
    text-decoration: underline;
}

.feedcard__verb {
    color: var(--color-muted);
    margin: 0 0.15rem;
}

.feedcard__book {
    color: var(--color-primary);
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
}

.feedcard__book:hover {
    text-decoration: underline;
}

.feedcard__time {
    font-size: 0.75rem;
    color: var(--color-muted);
    margin-top: 0.15rem;
}

.feedcard__time--right {
    text-align: right;
}

/* ---------- Review-type feed card ---------- */

.feedcard--review .feedcard__reviewbody {
    display: flex;
    gap: 0.75rem;
    margin-top: 0.5rem;
}


.feedcard__cover {
    flex-shrink: 0;
    width: 4.5rem;
    display: block;
}

.feedcard__cover img {
    width: 100%;
    height: auto;
    border-radius: 0.25rem;
    border: 1px solid var(--color-border);
    display: block;
}

.feedcard__reviewtext {
    flex: 1;
    min-width: 0;
}

.feedcard__author {
    color: var(--color-muted);
    font-size: 0.85rem;
    margin-bottom: 0.25rem;
}

.feedcard__rating {
    color: var(--color-secondary);
    font-size: 0.9rem;
    line-height: 1;
    margin-bottom: 0.4rem;
}

.feedcard__rating .star {
    color: var(--color-border);
}

.feedcard__rating .star--filled {
    color: var(--color-secondary);
}

.feedcard__excerpt {
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--color-text);
    margin: 0 0 0.5rem 0;
    /* 4-line clamp for visual consistency. */
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.feedcard__readmore {
    font-size: 0.85rem;
    font-weight: bold;
    color: var(--color-primary);
}

.feedcard__readmore:hover {
    text-decoration: underline;
}

/* ---------- Follow-type feed card (notification) ----------
   Quieter visual treatment — light primary tint background, smaller,
   single line + follow-back button. */

.feedcard--follow {
    background: rgba(43, 84, 66, 0.04); /* very light tint of primary */
    border-color: rgba(43, 84, 66, 0.12);
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
}

.feedcard__followtext {
    flex: 1;
    min-width: 0;
    font-size: 0.9rem;
    line-height: 1.4;
}

.feedcard__followtext .feedcard__time {
    display: inline;
    margin-left: 0.25rem;
}

.feedcard--follow .followtoggle {
    margin-top: 0;
}

/* ---------- Follow-group feed card (rolled-up notifications) ----------
   Renders a run of 4+ consecutive follow notifications as one collapsible
   <details> card. Reuses the .feedcard--follow tinted background so it
   reads as part of the same family. */

.feedcard--followgroup {
    display: block; /* override the flex layout of .feedcard--follow */
    padding: 0;
}

.feedcard--followgroup > summary {
    /* Suppress the default disclosure marker — we render our own chevron. */
    list-style: none;
    cursor: pointer;
    padding: 0.75rem 1rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    border-radius: 0.75rem;
}

.feedcard--followgroup > summary::-webkit-details-marker {
    display: none;
}

.feedcard--followgroup > summary:hover {
    background: rgba(43, 84, 66, 0.07);
}

.feedcard--followgroup > summary:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: -2px;
}

/* Avatar stack — overlapping circles, oldest on the right behind newer. */
.feedcard__avatarstack {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
}

.feedcard__avatarstackitem {
    display: inline-block;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    overflow: hidden;
    border: 2px solid #fff;
    background: var(--color-background);
    margin-left: -0.5rem;
    position: relative;
}

.feedcard__avatarstackitem:first-child {
    margin-left: 0;
}

.feedcard__avatarstackitem img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.feedcard__avatarstackitem--more {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    font-weight: bold;
    color: var(--color-muted);
    background: var(--color-background);
}

/* Chevron — flips when the <details> is open. */
.feedcard__followgroupchevron {
    flex-shrink: 0;
    width: 0.6rem;
    height: 0.6rem;
    border-right: 2px solid var(--color-muted);
    border-bottom: 2px solid var(--color-muted);
    transform: rotate(45deg);
    transition: transform 0.15s ease;
    margin-right: 0.25rem;
}

.feedcard--followgroup[open] .feedcard__followgroupchevron {
    transform: rotate(-135deg);
}

.feedcard__followgroupothers {
    color: var(--color-muted);
}

/* Expanded list of followers inside the group. */
.feedcard__followgrouplist {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid rgba(43, 84, 66, 0.12);
}

.feedcard__followgroupitem {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 1rem;
    border-bottom: 1px solid rgba(43, 84, 66, 0.08);
}

.feedcard__followgroupitem:last-child {
    border-bottom: none;
}

/* ---------- News-type feed card ----------
   Strong editorial treatment — magazine-feature feel. */

.feedcard--news {
    background: linear-gradient(180deg, #fff 0%, var(--color-background) 100%);
    border-color: var(--color-secondary);
    border-left-width: 3px;
    padding: 1.25rem 1.5rem;
}

/* ============================================================
   Side-by-side news card variant — used on the logged-in
   homepage feed and the /news/ listing page. Image sits to
   the left of the body on desktop, stacked on mobile.
   ============================================================ */

.feedcard--news--horizontal {
    display: flex;
    align-items: stretch;
    gap: 0;
}

.feedcard--news--horizontal .feedcard__newshero {
    flex-shrink: 0;
    width: 14rem;
    aspect-ratio: 2 / 1;
    height: auto;
    align-self: stretch;
}

.feedcard--news--horizontal .feedcard__newsbody {
    flex: 1;
    min-width: 0;
}

.feedcard__newslabel {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-secondary);
    margin-bottom: 0.5rem;
}

.feedcard__newsheadline {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.25rem;
    margin: 0 0 0.5rem 0;
    color: var(--color-primary);
    line-height: 1.25;
}

.feedcard__newsheadline a {
    color: var(--color-primary);
}

.feedcard__newsheadline a:hover {
    text-decoration: underline;
}

.feedcard__newslead {
    font-size: 0.95rem;
    line-height: 1.5;
    color: var(--color-text);
    margin: 0 0 0.75rem 0;
}

/* ============================================================
   Discover reviewers (empty-feed state)
   ============================================================ */

.home__discover {
    background: #fff;
    border-radius: 1rem;
    padding: 2rem;
    margin-bottom: 1.5rem;
}

.home__discovergrid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
    gap: 1rem;
    margin-top: 1rem;
}

.discovercard {
    background: var(--color-background);
    border-radius: 0.75rem;
    padding: 1rem;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
}

.discovercard__avatar {
    width: 4rem;
    height: 4rem;
    border-radius: 50%;
    overflow: hidden;
    border: 1px solid var(--color-border);
    background: #fff;
    display: block;
}

.discovercard__avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.discovercard__name {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-weight: bold;
    color: var(--color-primary);
    word-break: break-word;
}

.discovercard__name:hover {
    text-decoration: underline;
}

.discovercard__meta {
    font-size: 0.8rem;
    color: var(--color-muted);
}

.discovercard .followtoggle {
    /* Slightly bigger toggle in this context — primary action. */
    padding: 0.4rem 0.75rem;
    font-size: 0.85rem;
}

/* ============================================================
   Following / Followers management pages — append to your stylesheet
   ============================================================ */

.followpage {
    margin-bottom: 1rem;
}

.followpage__title {
    margin: 0 0 1rem 0;
    color: var(--color-text);
}

/* ---------- Tab strip ---------- */

.followpage__tabs {
    display: flex;
    gap: 0;
    border-bottom: 1px solid var(--color-border);
    margin-bottom: 1.5rem;
}

.followpage__tab {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1.25rem;
    color: var(--color-muted);
    font-weight: bold;
    border-bottom: 3px solid transparent;
    margin-bottom: -1px; /* sit on the container's border */
}

.followpage__tab:link,
.followpage__tab:visited {
    color: var(--color-muted);
}

.followpage__tab:hover {
    color: var(--color-primary);
    text-decoration: none;
    background: var(--color-background);
}

.followpage__tab--active {
    color: var(--color-primary);
    border-bottom-color: var(--color-secondary);
}

.followpage__tab--active:link,
.followpage__tab--active:visited {
    color: var(--color-primary);
}

.followpage__tabcount {
    background: var(--color-background);
    color: var(--color-muted);
    padding: 0.1rem 0.5rem;
    border-radius: 1rem;
    font-size: 0.8rem;
    font-weight: normal;
}

.followpage__tab--active .followpage__tabcount {
    background: var(--color-primary);
    color: #fff;
}

/* ---------- Toolbar ---------- */

.followpage__toolbar {
    display: flex;
    gap: 0.75rem;
    align-items: center;
    margin-bottom: 1rem;
    flex-wrap: wrap;
}

.followpage__search {
    flex: 1;
    min-width: 12rem;
    position: relative;
    display: flex;
    align-items: center;
}

.followpage__search input {
    width: 100%;
    padding-right: 4rem; /* room for the Clear link */
}

.followpage__searchclear {
    position: absolute;
    right: 0.75rem;
    font-size: 0.8rem;
    color: var(--color-muted);
}

.followpage__searchclear:hover {
    color: var(--color-primary);
}

.followpage__sort select {
    height: 100%;
    min-height: 2.75rem;
    cursor: pointer;
}

.visuallyhidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ---------- The list itself ---------- */

.followlist {
    background: #fff;
    border-radius: 1rem;
    padding: 0.5rem;
}

.followlist__rows {
    list-style: none;
    padding: 0;
    margin: 0;
}

.followlist__row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem;
    border-bottom: 1px solid var(--color-border);
    /* Override the global li indent. */
    margin-inline-start: 0;
}

.followlist__row:last-child {
    border-bottom: none;
}

.followlist__avatar {
    flex-shrink: 0;
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
    overflow: hidden;
    border: 1px solid var(--color-border);
    background: var(--color-background);
    display: block;
}

.followlist__avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.followlist__main {
    flex: 1;
    min-width: 0;
}

.followlist__username {
    display: inline-block;
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-weight: bold;
    color: var(--color-primary);
    word-break: break-word;
}

.followlist__username:hover {
    text-decoration: underline;
}

.followlist__meta {
    font-size: 0.8rem;
    color: var(--color-muted);
    margin-top: 0.15rem;
}

.followlist__actions {
    flex-shrink: 0;
}

/* ---------- Empty state ---------- */

.followlist__empty {
    text-align: center;
    padding: 3rem 1rem;
    color: var(--color-muted);
}

.followlist__empty p {
    margin: 0 0 1rem 0;
}

.followlist__empty p:last-child {
    margin-bottom: 0;
}

/* ---------- Pagination ---------- */

.followlist__pagenav {
    margin: 0.75rem 0.75rem;
    font-size: 0.9rem;
}

.followlist__pagenav--bottom {
    text-align: right;
    margin-top: 1rem;
}

.followlist__pagenav a {
    color: var(--color-primary);
    font-weight: bold;
}

.followlist__pagenav a:hover {
    text-decoration: underline;
}

/* ============================================================
   Profile actions menu (⋯) — append to your stylesheet
   ============================================================ */

/* Anchored to the top-right corner of the profile header, regardless
   of how the header itself is laid out (flex / float / block-level).
   The header element should already have position: relative — if it
   doesn't, this rule includes a fallback declaration on it. */
.userprofile__header {
    position: relative;
}

.userprofile__menuwrap {
    position: absolute;
    top: 0;
    right: 0;
}

.userprofile__menubutton {
    background: none;
    border: 1px solid transparent;
    color: var(--color-muted);
    font-size: 1.25rem;
    line-height: 1;
    padding: 0.25rem 0.5rem;
    border-radius: 0.4rem;
    cursor: pointer;
    font-family: inherit;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.userprofile__menubutton:hover,
.userprofile__menuwrap--open .userprofile__menubutton {
    background: var(--color-background);
    color: var(--color-primary);
    border-color: var(--color-border);
}

/* The dropdown panel itself. Anchored to the right edge of the
   wrap, drops down below the button with a small gap. */
.userprofile__menu {
    position: absolute;
    top: calc(100% + 0.25rem);
    right: 0;
    min-width: 12rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
    padding: 0.25rem;
    z-index: 100;
}

.userprofile__menu[hidden] {
    display: none;
}

.userprofile__menuitem {
    display: block;
    width: 100%;
    background: none;
    border: none;
    padding: 0.5rem 0.75rem;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.9rem;
    color: var(--color-text);
    border-radius: 0.3rem;
    transition: background 0.1s, color 0.1s;
}

.userprofile__menuitem:hover,
.userprofile__menuitem:focus {
    background: var(--color-background);
    outline: none;
}

.userprofile__menuitem:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* Destructive items (Block, eventually Report) get a danger tint
   on hover so users know it's significant. */
.userprofile__menuitem--danger {
    color: #c00;
}

.userprofile__menuitem--danger:hover,
.userprofile__menuitem--danger:focus {
    background: #fff5f5;
    color: #c00;
}

/* ============================================================
   News editor styles — /admin/news/news.css
   ============================================================ */

/* ---------- News list ---------- */

.newslist {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin-top: 1rem;
}

.newslist__row {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.75rem;
    padding: 0.75rem;
}

.newslist__thumb {
    flex-shrink: 0;
    width: 5rem;
    height: 5rem;
    border-radius: 0.5rem;
    overflow: hidden;
    background: var(--color-background);
    display: block;
}

.newslist__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.newslist__thumb--empty {
    background: var(--color-background);
    border: 1px dashed var(--color-border);
}

.newslist__main {
    flex: 1;
    min-width: 0;
}

.newslist__headline {
    display: block;
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.1rem;
    font-weight: bold;
    color: var(--color-primary);
    margin-bottom: 0.25rem;
}

.newslist__headline:hover {
    text-decoration: underline;
}

.newslist__meta {
    font-size: 0.8rem;
    color: var(--color-muted);
    margin-bottom: 0.5rem;
}

.newslist__genres {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
}

.newslist__genrepill {
    display: inline-block;
    background: var(--color-background);
    color: var(--color-muted);
    font-size: 0.7rem;
    padding: 0.15rem 0.5rem;
    border-radius: 1rem;
}

.newslist__actions {
    display: flex;
    gap: 0.4rem;
    flex-shrink: 0;
}

.newslist__deleteform {
    display: inline;
    margin: 0;
}

/* ---------- News edit form ---------- */

.newsform {
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.75rem;
    padding: 1.5rem;
    max-width: 48rem;
}

.newsform__field {
    margin-bottom: 1.25rem;
}

.newsform__field:last-of-type {
    margin-bottom: 0;
}

.newsform__field label {
    display: block;
    font-weight: bold;
    margin-bottom: 0.4rem;
    color: var(--color-primary);
}

.newsform__optional {
    font-weight: normal;
    color: var(--color-muted);
    font-size: 0.85rem;
}

.newsform__field input[type="text"],
.newsform__field input[type="url"],
.newsform__field textarea {
    width: 100%;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: 0.4rem;
    font-family: inherit;
    font-size: 0.95rem;
    box-sizing: border-box;
}

.newsform__field input[type="text"]:focus,
.newsform__field input[type="url"]:focus,
.newsform__field textarea:focus {
    outline: none;
    border-color: var(--color-primary);
}

.newsform__field textarea {
    resize: vertical;
    min-height: 8rem;
}

.newsform__hint {
    font-size: 0.8rem;
    color: var(--color-muted);
    margin-top: 0.3rem;
}

.newsform__error {
    color: #c00;
    font-size: 0.85rem;
    margin-top: 0.3rem;
}

.newsform__currentimage {
    margin-bottom: 0.5rem;
}

.newsform__currentimage img {
    display: block;
    max-width: 100%;
    max-height: 16rem;
    border: 1px solid var(--color-border);
    border-radius: 0.4rem;
    margin-bottom: 0.4rem;
}

.newsform__removeimage {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: normal;
    color: #c00;
    font-size: 0.85rem;
    cursor: pointer;
}

.newsform__buttons {
    margin-top: 1.5rem;
    display: flex;
    gap: 0.6rem;
}

/* Chosen plays nice with our form widths. */
.newsform .chosen-container {
    width: 100% !important;
}

/* ============================================================
   News card additions for the homepage feed.
   REPLACES the Phase 3 .feedcard--news block in your stylesheet.
   ============================================================ */

.feedcard--news {
    background: #fff;
    border: 1px solid var(--color-border);
    border-bottom: 2px solid var(--color-secondary);
    padding: 0;
    overflow: hidden;
}

/* Lead image hero — full-width, auto height. */
.feedcard__newshero {
    display: block;
    width: 100%;
    aspect-ratio: 2 / 1;
    background: var(--color-background);
    overflow: hidden;
}

.feedcard__newshero img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.feedcard__newsbody {
    padding: 1.25rem 1.5rem;
}

/* Label row sits above the headline and holds "NEWS" + any genre pills. */
.feedcard__newslabelrow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.5rem;
}

.feedcard__newslabel {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-secondary);
}

.feedcard__newsgenre {
    display: inline-block;
    font-size: 0.7rem;
    padding: 0.15rem 0.55rem;
    background: var(--color-background);
    color: var(--color-muted);
    border-radius: 1rem;
}

.feedcard__newsheadline {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.35rem;
    margin: 0 0 0.4rem 0;
    color: var(--color-primary);
    line-height: 1.25;
}

.feedcard__newsheadline a {
    color: var(--color-primary);
}

.feedcard__newsheadline a:hover {
    text-decoration: underline;
}

.feedcard__newsbyline {
    font-size: 0.8rem;
    color: var(--color-muted);
    margin-bottom: 0.75rem;
}

.feedcard__newslead {
    font-size: 0.95rem;
    line-height: 1.55;
    color: var(--color-text);
    margin: 0 0 0.75rem 0;
}

.feedcard__newslead br + br {
    /* Slight extra space when there are double-line-breaks (paragraphs)
       since nl2br just inserts <br>s. */
    line-height: 2;
}

/* ============================================================
   Profile-page news card — append to your stylesheet.
   Compact, horizontal layout matching the review cards on the
   user profile page. Distinct from the homepage feed news card
   (which is a full-bleed editorial hero).
   ============================================================ */

.userprofilenews {
    display: flex;
    gap: 1rem;
    padding: 1rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-bottom: 2px solid var(--color-secondary);
    border-radius: 0.5rem;
}

.userprofilenews__thumb {
    flex-shrink: 0;
    width: 6rem;
    height: 6rem;
    border-radius: 0.4rem;
    overflow: hidden;
    background: var(--color-background);
    display: block;
}

.userprofilenews__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Placeholder for news posts without an image. */
.userprofilenews__thumb--empty {
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--color-secondary) 0%, var(--color-primary) 100%);
    color: #fff;
    font-size: 0.7rem;
    font-weight: bold;
    letter-spacing: 0.12em;
}

.userprofilenews__body {
    flex: 1;
    min-width: 0;
}

.userprofilenews__kicker {
    display: inline-block;
    font-size: 0.65rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-secondary);
    margin-bottom: 0.25rem;
}

.userprofilenews__headline {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.05rem;
    margin: 0 0 0.25rem 0;
    color: var(--color-primary);
    line-height: 1.3;
}

.userprofilenews__headline a {
    color: var(--color-primary);
}

.userprofilenews__headline a:hover {
    text-decoration: underline;
}

.userprofilenews__date {
    font-size: 0.75rem;
    color: var(--color-muted);
    margin-bottom: 0.5rem;
}

.userprofilenews__lead {
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--color-text);
    margin: 0 0 0.5rem 0;
    /* 3-line clamp for visual consistency with review excerpts. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.userprofilenews__readmore {
    display: inline-block;
    font-size: 0.8rem;
    font-weight: bold;
    color: var(--color-primary);
    margin-bottom: 0.5rem;
}

.userprofilenews__readmore:hover {
    text-decoration: underline;
}

.userprofilenews__genres {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.4rem;
}

.userprofilenews__genre {
    display: inline-block;
    font-size: 0.7rem;
    padding: 0.15rem 0.55rem;
    background: var(--color-background);
    color: var(--color-muted);
    border-radius: 1rem;
}

/* ============================================================
   Profile-page blog card — append to your stylesheet.
   Compact, horizontal layout matching the news cards on the
   user profile page. Distinct from the homepage blog cards.

   Mirrors .userprofilenews structurally; differs in:
     - bottom border uses --color-primary (green) instead of
       --color-secondary (orange), so news vs blog are visually
       separable in the timeline at a glance
     - kicker text uses --color-primary
     - empty-state placeholder gradient is reversed (primary->
       secondary) to mirror the news placeholder
     - single category tag instead of multiple genre pills
   ============================================================ */

.userprofileblog {
    display: flex;
    gap: 1rem;
    padding: 1rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-bottom: 2px solid var(--color-primary);
    border-radius: 0.5rem;
}

.userprofileblog__thumb {
    flex-shrink: 0;
    width: 6rem;
    height: 6rem;
    border-radius: 0.4rem;
    overflow: hidden;
    background: var(--color-background);
    display: block;
}

.userprofileblog__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Placeholder for blog posts without a hero image. Gradient runs
   primary->secondary, the reverse of the news placeholder. */
.userprofileblog__thumb--empty {
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
    color: #fff;
    font-size: 0.7rem;
    font-weight: bold;
    letter-spacing: 0.12em;
}

.userprofileblog__body {
    flex: 1;
    min-width: 0;
}

.userprofileblog__kicker {
    display: inline-block;
    font-size: 0.65rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-primary);
    margin-bottom: 0.25rem;
}

.userprofileblog__headline {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.05rem;
    margin: 0 0 0.25rem 0;
    color: var(--color-primary);
    line-height: 1.3;
}

.userprofileblog__headline a {
    color: var(--color-primary);
}

.userprofileblog__headline a:hover {
    text-decoration: underline;
}

.userprofileblog__date {
    font-size: 0.75rem;
    color: var(--color-muted);
    margin-bottom: 0.5rem;
}

.userprofileblog__lead {
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--color-text);
    margin: 0 0 0.5rem 0;
    /* 3-line clamp, matching the news lead. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.userprofileblog__readmore {
    display: inline-block;
    font-size: 0.8rem;
    font-weight: bold;
    color: var(--color-primary);
    margin-bottom: 0.5rem;
}

.userprofileblog__readmore:hover {
    text-decoration: underline;
}

/* Single category tag (vs the news card's multi-genre row). */
.userprofileblog__categories {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.4rem;
}

.userprofileblog__category {
    display: inline-block;
    font-size: 0.7rem;
    padding: 0.15rem 0.55rem;
    background: var(--color-background);
    color: var(--color-muted);
    border-radius: 1rem;
}

/* The category is rendered as <a> when blogcategory.slug is present,
   <span> otherwise. Style the link variant with a hover lift. */
a.userprofileblog__category:link,
a.userprofileblog__category:visited {
    color: var(--color-muted);
    text-decoration: none;
}

a.userprofileblog__category:hover {
    background: var(--color-primary);
    color: #fff;
    text-decoration: none;
}

/* ============================================================
   News section — append to your stylesheet.
   Styles for /news/, /news/<id>/<slug>/, the homepage news strip,
   and the news share button.
   ============================================================ */

/* ---------- /news/ listing page ---------- */

.newssection {
    margin-bottom: 1rem;
}

.newssection__header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 1rem;
    margin-bottom: 1rem;
}

.newssection__title {
    margin: 0;
    color: var(--color-primary);
}

.newssection__rsslink {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    color: var(--color-muted);
    font-size: 0.85rem;
    font-weight: bold;
}

.newssection__rsslink:link,
.newssection__rsslink:visited {
    color: var(--color-muted);
}

.newssection__rsslink:hover {
    color: var(--color-secondary);
}

.newssection__rsslink svg {
    width: 1rem;
    height: 1rem;
}

/* Filter chip strip. */
.newsfilter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 1.5rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--color-border);
}

.newsfilter__chip {
    display: inline-block;
    padding: 0.35rem 0.8rem;
    background: var(--color-background);
    color: var(--color-muted);
    border-radius: 1rem;
    font-size: 0.85rem;
    font-weight: bold;
    text-decoration: none;
    transition: background 0.15s, color 0.15s;
}

.newsfilter__chip:link,
.newsfilter__chip:visited {
    color: var(--color-muted);
}

.newsfilter__chip:hover {
    background: var(--color-border);
    color: var(--color-primary);
    text-decoration: none;
}

.newsfilter__chip--active,
.newsfilter__chip--active:link,
.newsfilter__chip--active:visited {
    background: var(--color-primary);
    color: #fff;
}

.newsfilter__chip--active:hover {
    background: var(--color-secondary);
    color: #fff;
}

.newsfilter__divider {
    color: var(--color-border);
    margin: 0 0.2rem;
    font-weight: normal;
}

.newssection__empty {
    text-align: center;
    padding: 3rem 1rem;
    color: var(--color-muted);
}

.newssection__pagenav {
    margin: 0.75rem 0;
    font-size: 0.9rem;
}

.newssection__pagenav--bottom {
    text-align: right;
    margin-top: 1.5rem;
}

.newssection__pagenav a {
    color: var(--color-primary);
    font-weight: bold;
}

.newssection__pagenav a:hover {
    text-decoration: underline;
}

/* The list itself reuses .feedcard / .feedcard--news from the
   homepage feed. Spacing between cards: */
.newslist__feed {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* ---------- /news/<id>/<slug>/ permalink page ---------- */

.newsarticle {
    background: #fff;
    border: 1px solid var(--color-border);
    border-bottom: 2px solid var(--color-secondary);
    border-radius: 0.75rem;
    overflow: hidden;
    margin: 0 auto 2rem auto;
    max-width: 48rem;
}

.newsarticle__hero {
    width: 100%;
    background: var(--color-background);
    margin: 0;
}

.newsarticle__hero img {
    display: block;
    width: 100%;
    height: auto;
}

.newsarticle__herocaption {
    display: block;
    padding: 0.75rem 2rem 0.75em 2rem;
    font-size: 0.85rem;
    line-height: 1.45;
    color: var(--color-muted);
    border-top: 1px solid var(--color-border);
    background: var(--color-background);
    padding-top: 0.75rem;
}

.newsarticle__caption {
    display: block;
    color: var(--color-text);
}

.newsarticle__attribution {
    display: block;
    margin-top: 0.25rem;
    font-size: 0.75rem;
    color: var(--color-muted-light);
    font-style: italic;
}

.newsarticle__body {
    padding: 2rem;
}

.newsarticle__kicker {
    font-size: 0.75rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--color-secondary);
    margin-bottom: 0.75rem;
}

.newsarticle__headline {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.85rem;
    line-height: 1.2;
    color: var(--color-primary);
    margin: 0 0 0.75rem 0;
}

.newsarticle__meta {
    color: var(--color-muted);
    font-size: 0.9rem;
    margin-bottom: 1rem;
}

.newsarticle__meta a {
    color: var(--color-muted);
    font-weight: bold;
}

.newsarticle__meta a:hover {
    color: var(--color-primary);
    text-decoration: underline;
}

.newsarticle__metasep {
    margin: 0 0.4rem;
    color: var(--color-border);
}

.newsarticle__genres {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 1.25rem;
}

.newsarticle__genrepill {
    display: inline-block;
    padding: 0.2rem 0.65rem;
    background: var(--color-background);
    color: var(--color-muted);
    border-radius: 1rem;
    font-size: 0.75rem;
    font-weight: bold;
    text-decoration: none;
    transition: background 0.15s, color 0.15s;
}

.newsarticle__genrepill:link,
.newsarticle__genrepill:visited {
    color: var(--color-muted);
}

.newsarticle__genrepill:hover {
    background: var(--color-secondary);
    color: #fff;
    text-decoration: none;
}

.newsarticle__lead {
    font-size: 1.05rem;
    line-height: 1.65;
    color: var(--color-text);
    margin-bottom: 1.5rem;
}

.newsarticle__actions {
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
}

.newsarticle__readbutton {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.6rem 1.2rem;
    background: var(--color-primary);
    color: #fff;
    border: 1px solid var(--color-primary);
    border-radius: 0.5rem;
    font-size: 0.95rem;
    font-weight: bold;
    text-decoration: none;
    transition: background 0.15s, border-color 0.15s;
}

.newsarticle__readbutton:link,
.newsarticle__readbutton:visited {
    color: #fff;
}

.newsarticle__readbutton:hover {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
    text-decoration: none;
}

.newsarticle__back {
    margin: 0;
    padding-top: 1rem;
    border-top: 1px solid var(--color-border);
    font-size: 0.9rem;
}

.newsarticle__back a {
    color: var(--color-muted);
    font-weight: bold;
}

.newsarticle__back a:hover {
    color: var(--color-primary);
    text-decoration: underline;
}

/* News share button — same styling pattern as the book share button. */
.newssharebutton {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.6rem 1.2rem;
    background: var(--color-background);
    color: var(--color-primary);
    border: 1px solid var(--color-primary);
    border-radius: 0.5rem;
    font-size: 0.95rem;
    font-weight: bold;
    cursor: pointer;
    font-family: inherit;
}

.newssharebutton:hover {
    background: var(--color-secondary);
    color: #fff;
    border-color: var(--color-secondary);
}

.newssharebutton svg {
    width: 1em;
    height: 1em;
}

/* ---------- Homepage news strip (logged-out only) ---------- */

.home__newsstrip {
    background: #fff;
    border-radius: 1rem;
    padding: 2rem;
    margin-bottom: 1.5rem;
}

.home__newsstripheader {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 1rem;
    margin-bottom: 1rem;
}

.home__newsstriplink {
    color: var(--color-muted);
    font-size: 0.9rem;
    font-weight: bold;
}

.home__newsstriplink:link,
.home__newsstriplink:visited {
    color: var(--color-muted);
}

.home__newsstriplink:hover {
    color: var(--color-primary);
}

.home__newsstripgrid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
}

/* Buy-button base. Defaults to the neutral slate-blue treatment;
   variants below override colour to express hierarchy:
     .bookbuybutton--bookshop     → primary, solid --color-tertiary
     .bookbuybutton--amazon       → demoted, --color-tertiary-light tint
     .bookbuybutton--amazon.bookbuybutton--solo
                                  → Amazon promoted back to solid blue
                                    when it's the only buyable option
                                    (avoids visually merging with the
                                    adjacent --unavailable pill).
     .bookbuybutton--unavailable  → disabled "not on Bookshop" indicator
   The bare .bookbuybutton class is left intact so any other page
   using it (legacy callers, etc.) renders the same as before. */
.bookbuybutton {
    margin-top: 0px;
    background: var(--color-tertiary);
    color: #fff;
    padding: 0.5rem 1rem;
    border-radius: 0.5em;
    border: 1px solid var(--color-tertiary);
    font-size: 0.875rem;
    cursor: pointer;
    align-items: center;
    display: inline-flex;
    gap: 0.25rem;
    height: 2.5rem;
    font-family: inherit;
    text-decoration: none;
}

.bookbuybutton:link,
.bookbuybutton:visited {
    color: #fff;
}

.bookbuybutton:hover {
    background: var(--color-tertiary-dark);
    border-color: var(--color-tertiary-dark);
    text-decoration: none;
}

.bookbuybutton svg {
    width: 1em;
    height: 1em;
}

/* --- Primary: Bookshop.org. Solid --color-tertiary; sits at the top
   of the visual hierarchy when paired with a tinted Amazon button.
   Also used when Bookshop is the only retailer (state A). Inherits
   the base .bookbuybutton colours rather than re-declaring them, so
   this rule exists mostly as a documented hook for future tweaks. */
.bookbuybutton--bookshop,
.bookbuybutton--bookshop:link,
.bookbuybutton--bookshop:visited {
    background: var(--color-tertiary);
    border-color: var(--color-tertiary);
    color: #fff;
}

.bookbuybutton--bookshop:hover {
    background: var(--color-tertiary-dark);
    border-color: var(--color-tertiary-dark);
}

/* --- Demoted: Amazon (state B). Same hue as Bookshop but tinted —
   tonal hierarchy rather than chromatic. The Amazon button is still
   clearly a buy button; Bookshop just reads as the recommendation. */
.bookbuybutton--amazon,
.bookbuybutton--amazon:link,
.bookbuybutton--amazon:visited {
    background: var(--color-tertiary-light);
    color: var(--color-tertiary-dark);
    border-color: var(--color-tertiary-light);
}

.bookbuybutton--amazon:hover {
    /* Step one shade deeper than the resting tint. Re-uses the
       primary's resting colour for the border to give a clean edge
       on hover without inventing a new token. */
    background: #d4dbe6;
    border-color: var(--color-tertiary);
    color: var(--color-tertiary-dark);
}

/* --- Solo modifier: applied when Amazon is the only buyable option
   (state C). Promotes it back to the solid-blue primary treatment so
   it doesn't merge with the adjacent --unavailable indicator, which
   also sits on --color-tertiary-light. */
.bookbuybutton--amazon.bookbuybutton--solo,
.bookbuybutton--amazon.bookbuybutton--solo:link,
.bookbuybutton--amazon.bookbuybutton--solo:visited {
    background: var(--color-tertiary);
    border-color: var(--color-tertiary);
    color: #fff;
}

.bookbuybutton--amazon.bookbuybutton--solo:hover {
    background: var(--color-tertiary-dark);
    border-color: var(--color-tertiary-dark);
    color: #fff;
}

/* --- Disabled state for "Unavailable on Bookshop". A non-actionable
   <span> (not a link/button) — keeps assistive tech from announcing it
   as an interactive control. Strikethrough is applied to the label
   only, not the icon, so the icon doesn't look broken. */
.bookbuybutton--unavailable {
    background: var(--color-tertiary-light);
    color: var(--color-muted-light);
    border-color: var(--color-border);
    cursor: not-allowed;
}

.bookbuybutton--unavailable:hover {
    /* Override base :hover so it doesn't change on mouseover. */
    background: var(--color-tertiary-light);
    border-color: var(--color-border);
}

.bookbuybutton--unavailable .bookbuybutton__label {
    text-decoration: line-through;
    text-decoration-thickness: 1px;
}

.bookbuybutton--unavailable .bookbuybutton__icon {
    display: inline-flex;
    align-items: center;
}

/* ============================================================
   Affiliate disclosure

   Small, muted paragraph that sits below the action button
   cluster on the book page. Visually subtle so it doesn't
   compete with the buy button, but legible enough to satisfy
   the FTC's "clear and conspicuous" requirement.
   ============================================================ */

.affiliate-disclosure {
    clear: both;
    margin: 1rem 0 0 0;
    padding: 0.65rem 0.75rem;
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--color-muted);
    background: var(--color-background);
    border: 1px solid var(--color-border);
    border-radius: 0.4rem;
}

.affiliate-disclosure a {
    color: var(--color-muted);
    text-decoration: underline;
}

.affiliate-disclosure a:hover {
    color: var(--color-primary);
}

/* ============================================================
   Booklist privacy controls — append to your stylesheet.

   Two visible elements:
     - A small privacy icon on each non-public booklist tab,
       sitting between the title and the count badge.
     - A segmented pill group in the control panel for
       changing the active list's privacy (public / unlisted
       / private). Mirrors the active tab's current state.

   Public lists deliberately have no tab marker — public is the
   expected default, so only the "different" states need a badge
   (the GitHub repo pattern). This keeps the tab strip uncluttered
   for users whose lists are mostly public.
   ============================================================ */

/* ---------- Tab privacy marker ---------- */

.booklisttabprivacy {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 0.9rem;
    height: 0.9rem;
    margin-left: 0.4rem;
    margin-right: 0.2rem;
    opacity: 0.7;
    color: currentColor;
    vertical-align: middle;
    /* Float right so it sits cleanly between the title (which
       floats left) and the count badge (also right-floated) */
    float: right;
    margin-top: 0.35rem;
}

.booklisttabprivacy svg {
    width: 100%;
    height: 100%;
    display: block;
}

.booklisttab.active .booklisttabprivacy,
.booklisttab:hover .booklisttabprivacy {
    opacity: 0.95;
}

/* ---------- Control panel layout ---------- */

/* Override the existing .booklistcontrolpanel so the filter input
   and pill group sit side-by-side with proper alignment. The
   existing rule uses `overflow: auto` for clearfix; this replaces
   it with flexbox while keeping the same visual chrome. */

.booklistcontrolpanel {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    overflow: visible;
}

.booklistcontrolpanel #booklistbookfilter {
    flex: 1;
    min-width: 14rem;
    margin: 0;
}

/* ---------- "Privacy" label ---------- */

.booklistprivacylabel {
    font-size: 0.7rem;
    color: var(--color-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: bold;
    flex-shrink: 0;
}

/* ---------- The pill group ---------- */

.booklistprivacygroup {
    display: inline-flex;
    background: var(--color-background);
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    padding: 2px;
    gap: 2px;
    flex-shrink: 0;
}

.booklistprivacypill {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.4rem 0.7rem;
    border-radius: 0.35rem;
    font-size: 0.825rem;
    font-weight: 500;
    color: var(--color-muted);
    cursor: pointer;
    background: transparent;
    border: none;
    font-family: inherit;
    transition: background 0.15s, color 0.15s, transform 0.15s;
}

.booklistprivacypill svg {
    width: 0.95rem;
    height: 0.95rem;
    flex-shrink: 0;
}

.booklistprivacypill:hover:not(.booklistprivacypill--active):not(:disabled) {
    background: rgba(43, 84, 66, 0.06);
    color: var(--color-primary);
}

.booklistprivacypill--active {
    background: var(--color-primary);
    color: #fff;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}

.booklistprivacypill--active:hover {
    background: var(--color-primary);
    color: #fff;
}

.booklistprivacypill:disabled {
    cursor: wait;
    opacity: 0.7;
}

/* Brief pulse on save — tactile feedback that the click registered
   without being noisy. Triggered by JS adding --saving for ~250ms. */
.booklistprivacypill--saving {
    transform: scale(0.94);
}

/* ---------- Inline error message ---------- */

.booklistprivacyerror {
    display: inline-block;
    margin-left: 0.5rem;
    padding: 0.25rem 0.6rem;
    background: #fff5f5;
    color: #c00;
    border: 1px solid #f5c6c6;
    border-radius: 0.25rem;
    font-size: 0.8rem;
    font-weight: normal;
    vertical-align: middle;
    flex-basis: 100%;
}

/* ============================================================
   Profile-page public lists strip — append to your stylesheet.

   Sits between the bio/follow row (via .userprofile__stats) and
   the activity timeline (.userprofile__reviews). Each card
   shows up to 4 book covers in a horizontal row, with the list
   title and book count below.

   Phase 1: cards are display-only (no link target, no hover
   pointer). Phase 2 will turn the cards into <a> elements
   pointing to /users/{username}/lists/{slug}, at which point
   the hover styles will make sense to enable.
   ============================================================ */

.profilelists {
    margin-top: 1.5rem;
    margin-bottom: 1.5rem;
}

.profilelists__title {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    color: var(--color-primary);
    font-size: 1.25rem;
    margin: 0 0 1rem 0;
}

/* Responsive grid — 3 cards per row on desktop, 2 on tablet,
   1 on mobile. Auto-fill keeps things tidy regardless of how
   many lists the user has (1 to 6). */
.profilelists__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 1rem;
}

/* ---------- Card ---------- */

.profilelistcard {
    background: #fff;
    border: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-muted);
    border-radius: 0.75rem;
    padding: 1rem;
    /* No cursor / hover state in Phase 1 — cards aren't clickable
       yet. Phase 2 will add `a.profilelistcard` hover styles. */
}

/* ---------- Cover row ----------
   Four covers in a row, slightly overlapping for visual density.
   The overlap is achieved with negative margin on covers 2-4.
   When the list has fewer than 4 books, the trailing slots are
   rendered with .profilelistcard__cover--empty (a neutral
   placeholder rectangle) so card heights stay consistent. */

.profilelistcard__covers {
    display: flex;
    align-items: flex-start;
    margin-bottom: 0.75rem;
    /* Padding-bottom gives the overlap room without clipping the
       drop-shadow effect from the slight tilt below. */
    padding-bottom: 0.25rem;
}

.profilelistcard__cover {
    flex: 1 1 0;
    aspect-ratio: 2 / 3;
    border-radius: 0.3rem;
    overflow: hidden;
    background: var(--color-background);
    border: 1px solid var(--color-border);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
    /* Slight overlap on covers 2-4 for visual interest.
       First cover sits flush to the left edge. */
}

.profilelistcard__cover + .profilelistcard__cover {
    margin-left: -0.4rem;
}

.profilelistcard__cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Empty placeholder slot — used when a list has fewer than 4
   books, so card heights remain uniform across the grid. Visually
   muted so it doesn't compete with real covers. */
.profilelistcard__cover--empty {
    background: var(--color-background);
    border-style: dashed;
    border-color: var(--color-border);
    box-shadow: none;
    opacity: 0.5;
}

/* ---------- Title + count row ---------- */

.profilelistcard__meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.profilelistcard__icon {
    flex-shrink: 0;
    width: 1.25rem;
    height: 1.25rem;
    color: var(--color-primary);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.profilelistcard__icon svg {
    width: 100%;
    height: 100%;
    display: block;
}

.profilelistcard__text {
    flex: 1;
    min-width: 0;
}

.profilelistcard__title {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-weight: bold;
    color: var(--color-primary);
    font-size: 0.95rem;
    line-height: 1.25;
    /* Single-line clamp so long titles don't push card heights around. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.profilelistcard__count {
    color: var(--color-muted);
    font-size: 0.8rem;
    margin-top: 0.15rem;
}

/* ============================================================
   Phase 2 CSS additions — append to your stylesheet.

   Two sections:
     1. Hover lift on profile list cards (now that they're links)
     2. Per-list page styles (/users/{username}/lists/{slug})
   ============================================================ */


/* ============================================================
   Profile list cards — link state additions.
   The base .profilelistcard rules are unchanged; these add the
   anchor-tag affordances now that the cards link to per-list
   pages. Append to your existing .profilelistcard rules.
   ============================================================ */

a.profilelistcard {
    text-decoration: none;
    color: inherit;
    display: block;
    transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
}

a.profilelistcard:link,
a.profilelistcard:visited {
    color: inherit;
    text-decoration: none;
}

a.profilelistcard:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
    border-color: var(--color-secondary);
    text-decoration: none;
}

a.profilelistcard:hover .profilelistcard__title {
    text-decoration: underline;
}


/* ============================================================
   Per-list page — /users/{username}/lists/{slug}
   ============================================================ */

.booklistpage {
    margin-bottom: 2rem;
}

/* ---------- Header section ---------- */

/* Small "BOOK LIST" eyebrow label above the page title. Orients
   the visitor that this is a curated list page. Color is the
   accent orange so it draws the eye without competing with the
   title itself. */

.booklistpage__kicker {
    font-size: 0.7rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-secondary);
    margin-bottom: 0.4rem;
}

.booklistpage__header {
    background: #fff;
    border: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-muted);
    border-radius: 1rem;
    padding: 1.5rem;
    margin-top: 1rem;
    margin-bottom: 1.5rem;
}

.booklistpage__title {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

.booklistpage__icon {
    flex-shrink: 0;
    width: 1.75rem;
    height: 1.75rem;
    color: var(--color-primary);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.booklistpage__icon svg {
    width: 100%;
    height: 100%;
    display: block;
}

.booklistpage__heading {
    margin: 0;
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    color: var(--color-primary);
    font-size: 1.75rem;
    line-height: 1.2;
    flex: 1;
    min-width: 0;
    word-break: break-word;
}

/* Privacy badge — only shown to the owner on non-public lists. */
.booklistpage__privacybadge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.6rem;
    border-radius: 1rem;
    font-size: 0.75rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    flex-shrink: 0;
}

.booklistpage__privacybadge svg {
    width: 0.85rem;
    height: 0.85rem;
}

.booklistpage__privacybadge--unlisted {
    background: var(--color-tertiary-light);
    color: var(--color-tertiary-dark);
}

.booklistpage__privacybadge--private {
    background: #fff5f5;
    color: #c00;
}

/* ---------- Byline + count row ---------- */

.booklistpage__meta {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 0.75rem;
    flex-wrap: wrap;
}

.booklistpage__byline {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--color-muted);
    font-size: 0.9rem;
}

.booklistpage__byline:link,
.booklistpage__byline:visited {
    color: var(--color-muted);
    text-decoration: none;
}

.booklistpage__byline:hover {
    color: var(--color-primary);
    text-decoration: none;
}

.booklistpage__byline:hover .booklistpage__bylineuser {
    text-decoration: underline;
}

.booklistpage__avatar {
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--color-border);
}

.booklistpage__bylineuser {
    font-weight: bold;
    color: var(--color-primary);
}

.booklistpage__count {
    color: var(--color-muted);
    font-size: 0.9rem;
}

.booklistpage__count::before {
    content: "·";
    margin-right: 1rem;
    color: var(--color-border);
}

/* ---------- Description ---------- */

.booklistpage__description {
    margin: 0.75rem 0 0 0;
    color: var(--color-text);
    line-height: 1.5;
    /* Subtle quote-like treatment for description.
       Reads as "the curator's note" rather than body copy. */
    padding-left: 1rem;
    border-left: 3px solid var(--color-secondary);
    font-size: 0.95rem;
}

/* ---------- Action buttons row ---------- */

.booklistpage__actions {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-top: 1rem;
}

.booklistpage__sharebtn {
    /* Inherits .booksharebutton — the existing styling matches the
       book detail page. No overrides needed unless we want a
       distinct treatment here. */
}

/* ---------- Books grid ----------
   Reuses the .booklistbook structure from /mybooks/booklistbooks.php
   so the visual treatment is identical between the management view
   and the public list view. The wrapping anchor is .booklistpage__bookwrap
   to namespace it from any future structural changes. */

.booklistpage__books {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
    gap: 0.75rem;
    margin-top: 1rem;
}

.booklistpage__bookwrap {
    text-decoration: none;
    color: inherit;
}

.booklistpage__bookwrap:link,
.booklistpage__bookwrap:visited {
    color: inherit;
    text-decoration: none;
}

.booklistpage__bookwrap:hover {
    text-decoration: none;
}

/* The .booklistbook card itself uses the existing styles from
   the /mybooks/ view. We only need a small adjustment for
   ratings, which weren't in the original card layout. */

.booklistpage__bookrating {
    color: var(--color-secondary);
    font-size: 0.85rem;
    line-height: 1;
    margin-top: auto;
    padding-top: 0.4rem;
}

.booklistpage__bookrating .star {
    color: var(--color-border);
}

.booklistpage__bookrating .star--filled {
    color: var(--color-secondary);
}

/* ---------- Empty state ---------- */

.booklistpage__empty {
    text-align: center;
    padding: 3rem 1rem;
    color: var(--color-muted);
    background: #fff;
    border-radius: 1rem;
    border: 1px solid var(--color-border);
}

/* ---------- Filter input inside the actions row ----------
   Leftmost item in .booklistpage__actions, matching the layout
   of the filter in /mybooks/index.php's .booklistcontrolpanel.
   The input picks up its visual styling (border, padding, font)
   from the generic `input {}` rule; this rule only handles
   layout within the flex row: grow to fill remaining space,
   stay above a usable minimum width. */

.booklistpage__filterinput {
    flex: 1;
    min-width: 14rem;
    margin: 0;
}

/* ---------- "No books match your search" message ----------
   Shown when the filter input has a value but every book is
   hidden. Shared between /mybooks/ (index.php) and the per-list
   page (list.php) — both pages render this element with the same
   class, just with distinct ids so each page's filter JS can
   target its own. */

.booklistemptysearch {
    text-align: center;
    padding: 1.5rem 1rem;
    margin-top: 1rem;
    color: var(--color-muted);
    background: #fff;
    border-radius: 1rem;
    border: 1px solid var(--color-border);
}

/* ============================================================
   Phase 3 CSS additions — append to your stylesheet.

   Three sections:
     1. Profile strip header layout — adds room for the
        "See all →" link next to the "Lists" heading
     2. All-lists page styles
     3. Empty-state styling for cards on the all-lists page
   ============================================================ */


/* ============================================================
   Profile strip header — replaces the bare h2.profilelists__title
   layout with a flex row that holds the heading on the left and
   the "See all" link on the right.
   ============================================================ */

.profilelists__header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1rem;
}

.profilelists__header .profilelists__title {
    margin: 0;
}

.profilelists__viewall {
    font-size: 0.9rem;
    font-weight: bold;
    color: var(--color-primary);
    flex-shrink: 0;
}

.profilelists__viewall:link,
.profilelists__viewall:visited {
    color: var(--color-primary);
}

.profilelists__viewall:hover {
    text-decoration: underline;
}


/* ============================================================
   All-lists page — /users/{username}/lists
   ============================================================ */

.userlistspage {
    margin-bottom: 2rem;
}

.userlistspage__header {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-top: 1rem;
    margin-bottom: 1.5rem;
    padding: 1.25rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-muted);
    border-radius: 1rem;
}

.userlistspage__byline {
    flex-shrink: 0;
    display: block;
    transition: transform 0.15s;
}

.userlistspage__byline:hover {
    transform: scale(1.03);
    text-decoration: none;
}

.userlistspage__avatar {
    width: 4rem;
    height: 4rem;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--color-border);
    display: block;
}

.userlistspage__title {
    flex: 1;
    min-width: 0;
}

.userlistspage__heading {
    margin: 0;
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    color: var(--color-primary);
    font-size: 1.5rem;
    line-height: 1.2;
    word-break: break-word;
}

.userlistspage__count {
    color: var(--color-muted);
    font-size: 0.9rem;
    margin-top: 0.25rem;
}

/* The grid itself reuses .profilelists__grid styles from Phase 1
   (3 columns desktop, 2 tablet, 1 mobile via auto-fill). The
   .userlistspage__grid class is here purely for namespace
   future-proofing — overrides go here if we ever need them. */
.userlistspage__grid {
    /* Inherits everything from .profilelists__grid */
}

/* Empty state — when the user has zero public lists. */
.userlistspage__empty {
    text-align: center;
    padding: 3rem 1.5rem;
    background: #fff;
    border-radius: 1rem;
    border: 1px solid var(--color-border);
    color: var(--color-muted);
}

.userlistspage__empty p {
    margin: 0 0 0.5rem 0;
}

.userlistspage__empty p:last-child {
    margin-bottom: 0;
}

.userlistspage__empty a {
    color: var(--color-primary);
    font-weight: bold;
}


/* ============================================================
   Empty list card state — shown on the all-lists page for
   public lists that have zero books. The profile strip filters
   these out, but here we want them visible so users see their
   complete inventory.

   Replaces the four cover slots with a single muted strip that
   reads "No books yet" — clearly intentional rather than a
   loading or broken state.
   ============================================================ */

.profilelistcard__emptycovers {
    /* Match the height of the regular .profilelistcard__covers
       block so empty cards align with non-empty ones in the grid.
       Aspect 2:3 with width 4.25rem (the regular cover) gives
       6.375rem height; the cover row also has padding-bottom 0.25rem.
       So the placeholder needs to be ~6.625rem. */
    display: flex;
    align-items: center;
    justify-content: center;
    height: 6.625rem;
    margin-bottom: 0.75rem;
    padding-bottom: 0.25rem;
    background: var(--color-background);
    border: 1px dashed var(--color-border);
    border-radius: 0.4rem;
    color: var(--color-muted);
    font-size: 0.85rem;
    font-style: italic;
}

/* ============================================================
   Search results page — append to your stylesheet.

   Card-based list of books with cover, title, author, and
   optional subjects. Mirrors the visual treatment of the
   .feedcard / .userprofilereview pattern: white background,
   1px border, bottom-border accent, hover lift.

   The whole card is a single <a>, so the entire surface is
   tappable on mobile.
   ============================================================ */

.searchresults {
    margin-bottom: 2rem;
}

/* ---------- Header — query echo + result count ---------- */

.searchresults__header {
    margin-bottom: 1.5rem;
}

.searchresults__title {
    margin: 0 0 0.5rem 0;
    color: var(--color-primary);
    font-size: 1.85rem;
    line-height: 1.2;
    word-break: break-word;
}

.searchresults__title em {
    color: var(--color-secondary);
    font-style: italic;
    font-weight: normal;
}

.searchresults__count {
    margin: 0;
    color: var(--color-muted);
    font-size: 0.9rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: bold;
}

/* ---------- Notice (errors and stop-word messages) ---------- */

.searchresults__notice {
    background: #fff;
    border: 1px solid var(--color-border);
    border-bottom: 2px solid var(--color-secondary);
    border-radius: 0.75rem;
    padding: 1.25rem 1.5rem;
    color: var(--color-text);
}

.searchresults__notice p {
    margin: 0;
}

/* ---------- The list ---------- */

.searchresults__list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

/* ---------- Individual result card ---------- */

.searchresult {
    display: flex;
    align-items: stretch;
    gap: 1rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-muted);
    border-radius: 0.75rem;
    padding: 1rem;
    text-decoration: none;
    color: inherit;
    transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}

.searchresult:link,
.searchresult:visited {
    color: inherit;
    text-decoration: none;
}

.searchresult:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.08);
    border-color: var(--color-secondary);
    text-decoration: none;
}

.searchresult:hover .searchresult__title {
    color: var(--color-secondary);
}

.searchresult:hover .searchresult__chevron {
    color: var(--color-secondary);
    transform: translateX(2px);
}

/* ---------- Cover ---------- */

.searchresult__cover {
    flex-shrink: 0;
    width: 5rem;
    aspect-ratio: 2 / 3;
    border-radius: 0.4rem;
    overflow: hidden;
    background: var(--color-background);
    border: 1px solid var(--color-border);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.searchresult__cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* ---------- Body — title, author, subjects ---------- */

.searchresult__body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.25rem;
}

.searchresult__title {
    margin: 0;
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.15rem;
    font-weight: bold;
    line-height: 1.25;
    color: var(--color-primary);
    word-break: break-word;
    transition: color 0.15s;
    /* 2-line clamp so a long title doesn't blow out card height */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.searchresult__author {
    color: var(--color-muted);
    font-size: 0.9rem;
    line-height: 1.3;
}

.searchresult__author span {
    color: var(--color-text);
}

/* Subjects row — small pills under the author. Limited to 3
   subjects in PHP so the row never wraps awkwardly. */
.searchresult__subjects {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.4rem;
}

.searchresult__subject {
    display: inline-block;
    font-size: 0.7rem;
    padding: 0.15rem 0.55rem;
    background: var(--color-background);
    color: var(--color-muted);
    border-radius: 1rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: bold;
}

/* ---------- Chevron — affordance that the card is clickable ---------- */

.searchresult__chevron {
    flex-shrink: 0;
    align-self: center;
    color: var(--color-muted-light);
    font-size: 1.5rem;
    line-height: 1;
    transition: color 0.15s, transform 0.15s;
}

/* ---------- Empty state ---------- */

.searchresults__empty {
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 1rem;
    padding: 3rem 2rem;
    text-align: center;
}

.searchresults__emptyicon {
    width: 4rem;
    height: 4rem;
    margin: 0 auto 1rem auto;
    color: var(--color-muted-light);
    background: var(--color-background);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.searchresults__emptyicon svg {
    width: 2rem;
    height: 2rem;
}

.searchresults__emptytitle {
    margin: 0 0 0.5rem 0;
    color: var(--color-primary);
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-weight: bold;
    font-size: 1.4rem;
}

.searchresults__emptylead {
    margin: 0 0 1.5rem 0;
    color: var(--color-muted);
    line-height: 1.5;
}

.searchresults__emptylead em {
    color: var(--color-text);
    font-style: italic;
}

.searchresults__emptytips {
    list-style: none;
    padding: 0;
    margin: 0 auto 1.5rem auto;
    max-width: 22rem;
    text-align: left;
    color: var(--color-text);
    font-size: 0.9rem;
}

.searchresults__emptytips li {
    margin: 0 0 0.4rem 0;
    margin-inline-start: 0;
    padding-left: 1.25rem;
    position: relative;
    line-height: 1.4;
}

.searchresults__emptytips li::before {
    content: "•";
    color: var(--color-secondary);
    position: absolute;
    left: 0.4rem;
    font-weight: bold;
}

.searchresults__emptycta {
    margin: 0;
}

/* ============================================================
   Custom booklists — Phase 1 additions to your stylesheet.

   Two main sections:
     1. Tab strip overflow handling (horizontal scroll + fade)
     2. The "+ New list" tab and create modal
   ============================================================ */

/* ---------- Tab strip wrapper ----------
   Wraps the existing booklist tabs in a horizontally-scrolling row.
   The right-edge gradient fades the last visible tab to indicate
   there's more to the right. */

.booklisttabstrip {
    display: flex;
    flex-wrap: wrap; /* still wraps on desktop when there's room */
    align-items: flex-start;
    gap: 0;
    margin-bottom: 0.5rem;
    /* Floats inside .booklisttab still need clearing once we exit
       the strip context. */
    overflow: visible;
}

/* Spacer between the standard list group and custom lists. */
.booklisttabspacer {
    display: inline-block;
    width: 1.5rem;
    flex-shrink: 0;
}

/* ---------- "+ New list" tab ---------- */

.booklisttabnew {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem;
    font-size: 0.875rem;
    color: var(--color-primary);
    background: var(--color-background);
    border: 1px dashed var(--color-primary);
    border-radius: 0.5em;
    margin: 0 0.5rem 0.5rem 0;
    cursor: pointer;
    font-family: inherit;
    transition: background 0.15s, color 0.15s, border-style 0.15s;
}

.booklisttabnew:hover:not(.booklisttabnew--disabled) {
    background: var(--color-primary);
    color: #fff;
    border-style: solid;
}

.booklisttabnew--disabled {
    opacity: 0.5;
    cursor: not-allowed;
    border-style: dashed;
}

.booklisttabnew__icon,
.booklisttabnew__label {
    /* Mimic the inner padding that .booklisttabtitle and .booklisttabcount
       have inside regular tabs. Without this, the new-list button comes
       out ~0.5rem shorter than a regular tab. */
    padding: 0.25rem 0;
    line-height: 1;
}

.booklisttabnew__icon {
    font-size: 1rem;
    font-weight: bold;
}

/* ============================================================
   Create-new-list modal
   ============================================================ */

.newlistmodal {
    position: fixed;
    inset: 0;
    z-index: 9000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
}

.newlistmodal[hidden] {
    display: none;
}

.newlistmodal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}

.newlistmodal__panel {
    position: relative;
    width: 100%;
    max-width: 28rem;
    max-height: 90vh;
    background: #fff;
    border-radius: 1rem;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.newlistmodal__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem 1.25rem;
    border-bottom: 1px solid var(--color-border);
}

.newlistmodal__title {
    margin: 0;
    font-size: 1.25rem;
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    color: var(--color-primary);
}

.newlistmodal__close {
    background: none;
    border: none;
    font-size: 1.5rem;
    line-height: 1;
    color: var(--color-muted);
    cursor: pointer;
    padding: 0.25rem 0.5rem;
    border-radius: 0.3rem;
    font-family: inherit;
}

.newlistmodal__close:hover {
    background: var(--color-background);
    color: var(--color-primary);
}

.newlistmodal__body {
    padding: 1.25rem;
    overflow-y: auto;
}

.newlistmodal__field {
    margin-bottom: 1rem;
}

.newlistmodal__field:last-child {
    margin-bottom: 0;
}

.newlistmodal__field label {
    display: block;
    margin-bottom: 0.4rem;
    color: var(--color-primary);
    font-weight: bold;
    font-size: 0.9rem;
}

.newlistmodal__optional {
    color: var(--color-muted);
    font-weight: normal;
    font-size: 0.85rem;
}

.newlistmodal__field input[type="text"],
.newlistmodal__field textarea {
    width: 100%;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--color-border);
    border-radius: 0.4rem;
    font-family: inherit;
    font-size: 0.95rem;
    box-sizing: border-box;
    color: var(--color-text);
}

.newlistmodal__field input[type="text"]:focus,
.newlistmodal__field textarea:focus {
    outline: none;
    border-color: var(--color-primary);
}

.newlistmodal__field textarea {
    resize: vertical;
    min-height: 4rem;
}

.newlistmodal__help {
    margin: 0.3rem 0 0 0;
    font-size: 0.8rem;
    color: var(--color-muted);
}

/* Inside-modal privacy pill group inherits .booklistprivacygroup
   styles — but we want it full-width inside the modal. */
.newlistmodal__privacygroup {
    display: flex;
    width: 100%;
}

.newlistmodal__privacygroup .booklistprivacypill {
    flex: 1;
    justify-content: center;
}

.newlistmodal__error {
    margin-top: 1rem;
    padding: 0.75rem 1rem;
    background: #fff5f5;
    border: 1px solid #f5c6c6;
    color: #c00;
    border-radius: 0.4rem;
    font-size: 0.9rem;
}

.newlistmodal__footer {
    padding: 1rem 1.25rem;
    border-top: 1px solid var(--color-border);
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
}

.newlistmodal__cancel,
.newlistmodal__submit {
    padding: 0.5rem 1rem;
    border-radius: 0.5em;
    font-size: 0.9rem;
    font-weight: bold;
    cursor: pointer;
    font-family: inherit;
    border: 1px solid transparent;
}

.newlistmodal__cancel {
    background: #fff;
    color: var(--color-muted);
    border-color: var(--color-border);
}

.newlistmodal__cancel:hover {
    background: var(--color-background);
    color: var(--color-text);
}

.newlistmodal__submit {
    background: var(--color-primary);
    color: #fff;
    border-color: var(--color-primary);
}

.newlistmodal__submit:hover {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
}

.newlistmodal__submit:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* ============================================================
   Phase 2 of custom booklists — append to your stylesheet.

   Three sections:
     1. Owner "..." menu on the per-list page header
     2. Delete-confirmation modal additions (reuses .newlistmodal*)
     3. Small panel-size variant for the confirm-delete modal

   The edit modal reuses the existing .newlistmodal* styles from
   Phase 1 wholesale via the .editlistmodal class — no overrides
   needed. The confirm-delete modal also reuses .newlistmodal*
   but adds a "small panel" variant and a danger-button variant.
   ============================================================ */

/* ============================================================
   1. Owner menu on the per-list page (the "..." button).
   ============================================================ */

.booklistpage__menuwrap {
    position: relative;
    margin-left: auto; /* pushes the menu to the right edge of the title row */
    flex-shrink: 0;
}

.booklistpage__menubutton {
    background: none;
    border: 1px solid transparent;
    color: var(--color-muted);
    font-size: 1.25rem;
    line-height: 1;
    padding: 0.25rem 0.6rem;
    border-radius: 0.4rem;
    cursor: pointer;
    font-family: inherit;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.booklistpage__menubutton:hover,
.booklistpage__menuwrap--open .booklistpage__menubutton {
    background: var(--color-background);
    color: var(--color-primary);
    border-color: var(--color-border);
}

.booklistpage__menu {
    position: absolute;
    top: calc(100% + 0.25rem);
    right: 0;
    min-width: 12rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
    padding: 0.25rem;
    z-index: 100;
}

.booklistpage__menu[hidden] {
    display: none;
}

.booklistpage__menuitem {
    display: block;
    width: 100%;
    background: none;
    border: none;
    padding: 0.5rem 0.75rem;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.9rem;
    color: var(--color-text);
    border-radius: 0.3rem;
    transition: background 0.1s, color 0.1s;
}

.booklistpage__menuitem:hover,
.booklistpage__menuitem:focus {
    background: var(--color-background);
    outline: none;
}

/* Destructive items (Delete) get a danger tint on hover so users
   know it's significant. */
.booklistpage__menuitem--danger {
    color: #c00;
}

.booklistpage__menuitem--danger:hover,
.booklistpage__menuitem--danger:focus {
    background: #fff5f5;
    color: #c00;
}

/* The header title row uses flex so the menu can sit on the right. */
.booklistpage__title {
    /* These properties may already be set by Phase 1; declared here
       too so the menu's margin-left:auto behaviour works. */
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}

/* ============================================================
   2. Confirm-delete modal — small panel variant + danger button.

   The modal markup reuses .newlistmodal* classes wholesale; these
   rules just add a smaller max-width for the confirm dialog (it
   doesn't need 28rem of room for two short paragraphs) and a
   red variant of the submit button.
   ============================================================ */

.newlistmodal__panel--small {
    max-width: 24rem;
}

.confirmdeletemodal__lead {
    margin: 0 0 0.75rem 0;
    color: var(--color-text);
    line-height: 1.4;
    font-size: 1rem;
}

.confirmdeletemodal__detail {
    margin: 0;
    color: var(--color-muted);
    font-size: 0.9rem;
    line-height: 1.5;
}

/* Danger variant of the modal's primary button. */
.newlistmodal__submit--danger {
    background: #c00;
    border-color: #c00;
}

.newlistmodal__submit--danger:hover {
    background: #a00;
    border-color: #a00;
}

/* ============================================================
   Phase 3 of custom booklists — append to your stylesheet.

   Adds:
     1. The "Save to lists" button on the book page
     2. The popover that opens beneath it (checkbox list)
     3. Empty / loading / error states inside the popover
     4. Mobile adjustments (popover repositions to fit viewport)

   The status dropdown reuses the existing .booklistselect rules,
   so no changes there. The Favorite button is unchanged.
   ============================================================ */

/* ---------- Wrapper ---------- */

.savetolistswrap {
    position: relative;
    display: inline-flex;
}

/* ---------- The "Save to lists" trigger button ----------
   Visual language matches .bookfavoritebutton / .booksharebutton —
   ghost style, light background, primary green text. Becomes
   primary-styled when its popover is open. */

.savetolistsbutton {
    margin-top: 0;
    background: var(--color-background);
    color: var(--color-primary);
    padding: 0.5rem 1rem;
    border: 1px solid var(--color-primary);
    border-radius: 0.5em;
    font-size: 0.875rem;
    cursor: pointer;
    align-items: center;
    display: inline-flex;
    gap: 0.4rem;
    height: 2.5rem;
    font-family: inherit;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.savetolistsbutton:hover,
.savetolistsbutton[aria-expanded="true"] {
    background: var(--color-primary);
    color: #fff;
    border-color: var(--color-primary);
}

.savetolistsbutton svg {
    width: 1em;
    height: 1em;
}

/* ---------- Popover ---------- */

.savetolistspopover {
    position: absolute;
    top: calc(100% + 0.4rem);
    left: 0;
    z-index: 200;
    width: 18rem;
    max-width: calc(100vw - 2rem);
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.6rem;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    /* Subtle entrance — same visual feel as the privacy pills'
       active state, so the appearance reads as "intentional". */
    animation: savetolistspopover-fadein 0.12s ease-out;
}

.savetolistspopover[hidden] {
    display: none;
}

@keyframes savetolistspopover-fadein {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}

.savetolistspopover__header {
    padding: 0.6rem 0.9rem;
    border-bottom: 1px solid var(--color-border);
    font-size: 0.85rem;
    font-weight: bold;
    color: var(--color-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    background: var(--color-background);
}

/* ---------- Body — list of lists, or empty/loading/error states ---------- */

.savetolistspopover__body {
    flex: 1;
    overflow-y: auto;
    max-height: 16rem;
    padding: 0.4rem 0;
}

.savetolistspopover__list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.savetolistspopover__item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.45rem 0.9rem;
    margin-inline-start: 0;  /* override the global li indent */
    cursor: pointer;
    transition: background 0.1s;
}

.savetolistspopover__item:hover {
    background: var(--color-background);
}

.savetolistspopover__item input[type="checkbox"] {
    flex-shrink: 0;
    cursor: pointer;
    width: 1rem;
    height: 1rem;
    margin: 0;
    accent-color: var(--color-primary);
}

.savetolistspopover__item input[type="checkbox"]:disabled {
    cursor: wait;
    opacity: 0.6;
}

.savetolistspopover__item label {
    flex: 1;
    min-width: 0;
    cursor: pointer;
    font-weight: normal;
    color: var(--color-text);
    line-height: 1.3;
    /* Long titles wrap to a second line rather than truncating —
       custom list names often capture meaning in their tail words
       ("...for the long flight"), so truncation can hide intent. */
    word-break: break-word;
}

/* Small privacy indicator (globe / link / padlock) shown between
   the checkbox and the list title. Helps the user know whether
   adding the book to a list makes it publicly visible, unlisted,
   or private. Gray to stay quiet — the title is the row's primary
   content, the icon is just a hint. */

.savetolistspopover__privacyicon {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    color: var(--color-muted);
    cursor: help;  /* matches the title-tooltip affordance */
}

.savetolistspopover__privacyicon svg {
    width: 0.95rem;
    height: 0.95rem;
}

.savetolistspopover__loading,
.savetolistspopover__empty,
.savetolistspopover__error {
    padding: 1rem;
    text-align: center;
    color: var(--color-muted);
    font-size: 0.875rem;
    line-height: 1.4;
}

.savetolistspopover__error button {
    display: inline-block;
    margin-top: 0.4rem;
    padding: 0.3rem 0.75rem;
    background: #fff;
    color: var(--color-primary);
    border: 1px solid var(--color-primary);
    border-radius: 0.4rem;
    font-size: 0.85rem;
    cursor: pointer;
    font-family: inherit;
}

.savetolistspopover__error button:hover {
    background: var(--color-primary);
    color: #fff;
}

/* ---------- Footer with the "+ Create new list" link ---------- */

.savetolistspopover__footer {
    border-top: 1px solid var(--color-border);
    padding: 0.6rem 0.9rem;
    background: var(--color-background);
}

.savetolistspopover__createlink {
    display: inline-block;
    color: var(--color-primary);
    font-size: 0.875rem;
    font-weight: bold;
    text-decoration: none;
}

.savetolistspopover__createlink:hover {
    text-decoration: underline;
}

.savetolistspopover__createlink--disabled {
    color: var(--color-muted-light);
    cursor: not-allowed;
    pointer-events: none;
}

/* ============================================================
   Phase 4 of custom booklists — append to your stylesheet.

   Changes:
     1. Stronger divider between status/favorites and custom
        tabs in the booklist tab strip.
     2. The "..." owner-actions menu in the /mybooks/ control
        panel, with Edit / Delete items.
   ============================================================ */

/* ============================================================
   1. Divider in the booklist tab strip.

   The previous .booklisttabspacer was just empty horizontal
   space (1.5rem wide), which read as inconsistent gap rather
   than intentional grouping. Replacing the empty span with a
   vertical line — a clean visual signal that "what's to the
   right is a different category".

   The line uses primary-light and sits centered vertically.
   Spacing on either side gives it room to breathe.
   ============================================================ */

/* Divider between status/favorites tabs and custom lists.
   Replaces the previous transparent gap; the line + breathing
   space reads as intentional grouping. */
.booklisttabspacer {
    /* Reset: the old Phase 1 rule had width: 1.5rem; we now
       control width via padding + content, so explicitly clear it. */
    width: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: 0 0.85rem;
    /* Match the height of an adjacent tab so the line spans
       the full vertical extent of the tab row. */
    align-self: stretch;
    /* Fallback in case align-self: stretch doesn't take effect
       (e.g. on a row that's shorter than expected). */
    min-height: 3rem;
}

.booklisttabspacer::before {
    content: "";
    display: block;
    width: 2px;
    height: 2.5rem;
    border-radius: 1px;
    /* Solid muted line, slightly darker than --color-border so
       it's visible against the page background. */
    background: var(--color-muted-light);
    /* Faded ends so it doesn't look like a hard cut. */
    background: linear-gradient(
        180deg,
        transparent 0%,
        var(--color-muted-light) 25%,
        var(--color-muted) 50%,
        var(--color-muted-light) 75%,
        transparent 100%
    );
    opacity: 0.6;
}

/* ============================================================
   2. The "..." owner-actions menu in the /mybooks/ control
   panel. Opens Edit or Delete modals via the shared partials.

   Visual language matches the per-list page menu (in list.php).
   ============================================================ */

.booklistmenuwrap {
    position: relative;
    /* Push to the right edge of the flex container. */
    margin-left: auto;
    flex-shrink: 0;
}

.booklistmenuwrap[hidden] {
    display: none;
}

.booklistmenubutton {
    background: none;
    border: 1px solid transparent;
    color: var(--color-muted);
    font-size: 1.25rem;
    line-height: 1;
    padding: 0.4rem 0.7rem;
    border-radius: 0.4rem;
    cursor: pointer;
    font-family: inherit;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
    /* Match the height of the privacy pill group so the row
       stays tidy. */
    height: 2.25rem;
}

.booklistmenubutton:hover,
.booklistmenuwrap--open .booklistmenubutton {
    background: var(--color-background);
    color: var(--color-primary);
    border-color: var(--color-border);
}

.booklistmenu {
    position: absolute;
    top: calc(100% + 0.25rem);
    right: 0;
    min-width: 12rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
    padding: 0.25rem;
    z-index: 100;
}

.booklistmenu[hidden] {
    display: none;
}

.booklistmenuitem {
    display: block;
    width: 100%;
    background: none;
    border: none;
    padding: 0.5rem 0.75rem;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.9rem;
    color: var(--color-text);
    border-radius: 0.3rem;
    transition: background 0.1s, color 0.1s;
}

.booklistmenuitem:hover,
.booklistmenuitem:focus {
    background: var(--color-background);
    outline: none;
}

.booklistmenuitem--danger {
    color: #c00;
}

.booklistmenuitem--danger:hover,
.booklistmenuitem--danger:focus {
    background: #fff5f5;
    color: #c00;
}

/* ============================================================
   Phase 4b — Section labels for booklist groups.

   Replaces the previous .booklisttabspacer divider approach
   (which relied on a fragile vertical line between groups).
   The lists are now visually separated by being in two
   distinct strips, each with a small uppercase header above.

   THIS REPLACES the .booklisttabspacer rules from earlier
   phases — those styles can be left in place but won't be
   used (no more spacer elements rendered). If you'd like to
   remove them, find and delete .booklisttabspacer rules in
   your stylesheet. They're harmless if left.
   ============================================================ */

/* ---------- Group wrapper ---------- */

.booklistgroup {
    margin-bottom: 1rem;
}

.booklistgroup:last-of-type {
    /* The custom-lists group is followed immediately by the
       control panel, so we want a slightly tighter bottom
       margin than the standard-lists group has. */
    margin-bottom: 0.5rem;
}

/* ---------- Group header ----------
   Small uppercase label that anchors meaning to each row. The
   muted color and tracking sit it apart from primary content
   while making it clearly a "section divider" — pattern users
   are familiar with from settings pages, dashboards, etc. */

.booklistgroup__header {
    font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
    font-size: 0.7rem;
    font-weight: bold;
    color: var(--color-secondary);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: 0.5rem;
    /* Inline-flex so the optional "remaining" sub-label can sit
       on the same line, separated by space rather than a line break. */
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    flex-wrap: wrap;
}

/* The "X of Y remaining" sub-label inside the "Your lists" header.
   Even smaller and less emphatic — meta info, not a heading. */

.booklistgroup__headermeta {
    font-size: 0.7rem;
    font-weight: normal;
    color: var(--color-muted-light);
    text-transform: none;
    letter-spacing: normal;
}

/* ============================================================
   Share-caption styling — append to your stylesheet.

   Adds:
     1. .booklistpage__sharewrap — small wrapper around the
        share button + caption so they stack cleanly.
     2. .booklistpage__sharenote — the muted caption shown
        under the share button for owners viewing unlisted lists.
   ============================================================ */

.booklistpage__sharewrap {
    /* The button + caption sit in a small column so the caption
       wraps directly beneath the button. The wrap is inline-flex
       so it integrates into .booklistpage__actions like any other
       button — without it, an extra .booklistpage__sharenote
       paragraph would force the row to break. */
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.25rem;
}

.booklistpage__sharenote {
    /* Sub-text under the share button. Muted color and a small
       link icon make it read as "info about this thing" rather
       than as primary content. */
    margin: 0;
    font-size: 0.75rem;
    color: var(--color-muted);
    line-height: 1.3;
    display: flex;
    align-items: center;
    gap: 0.3rem;
    /* Match the button's left padding so the caption text aligns
       with the button label rather than the button edge. */
    padding-left: 0.25rem;
}

.booklistpage__sharenote svg {
    width: 0.85rem;
    height: 0.85rem;
    flex-shrink: 0;
    color: var(--color-muted);
}

/* ============================================================
   Share button + caption in the /mybooks/ control panel.

   Layout: the wrap stacks the button above the caption, both
   left-aligned. The wrap sits between the privacy pills and
   the "..." menu in the control panel row.

   Sizing matches the existing privacy pills and menu button so
   the row reads as a coherent toolbar rather than a grab-bag.
   ============================================================ */

.booklistsharebutton {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    background: var(--color-background);
    color: var(--color-primary);
    border: 1px solid var(--color-primary);
    border-radius: 0.4rem;
    padding: 0.4rem 0.8rem;
    font-family: inherit;
    font-size: 0.85rem;
    cursor: pointer;
    /* Match the height of the privacy pills (which are 2.25rem
       tall via padding) so the button aligns with them. */
    height: 2.25rem;
    line-height: 1;
    transition: background 0.15s, color 0.15s;
}

.booklistsharebutton:hover,
.booklistsharebutton:focus {
    background: var(--color-primary);
    color: #fff;
    outline: none;
}

.booklistsharebutton svg {
    width: 0.95rem;
    height: 0.95rem;
}

/* ============================================================
   Share button — refined version.

   Changes from the previous round:
     - .booklistsharewrap and .booklistsharenote rules can be
       removed (no longer rendered). They're harmless if left.
     - New :disabled state for the share button on private lists.

   Append the new rule to your stylesheet. The dead rules can
   stay — they just won't match anything.
   ============================================================ */

/* Disabled state — applied when the active list is private.
   The button stays in the layout (so the row doesn't jump on
   privacy changes) but loses its primary affordance: muted
   colors, not-allowed cursor, no hover transition. */
.booklistsharebutton:disabled {
    background: var(--color-background);
    color: var(--color-muted-light);
    border-color: var(--color-border);
    cursor: not-allowed;
}

.booklistsharebutton:disabled:hover,
.booklistsharebutton:disabled:focus {
    /* Override the existing hover that turns the button green. */
    background: var(--color-background);
    color: var(--color-muted-light);
    border-color: var(--color-border);
}

.booklistsharebutton:disabled svg {
    /* Ensure the icon picks up the muted color too. */
    color: var(--color-muted-light);
}

/* ============================================================
   Save-to-lists button — active state + counter pill.

   Mirrors the visual language of the other "this is on" patterns:
     - .bookfavoritebutton.bookfavorited (primary green, white text)
     - .booklistprivacypill--active (primary green, white text)
     - .booklisttabcount (the small pill on /mybooks/ tabs)

   The counter pill itself reuses the .booklisttabcount visuals so
   users see the same affordance in two places.
   ============================================================ */

/* Active state — applied when the book is in 1+ custom lists.
   The button is colored primary green, mirroring how the favorite
   button looks when the book has been favorited. */
.savetolistsbutton--active {
    background: var(--color-primary);
    color: #fff;
    border-color: var(--color-primary);
}

.savetolistsbutton--active:hover,
.savetolistsbutton--active:focus {
    /* Keep the same visual when hovered — already at "on" state. */
    background: var(--color-primary);
    color: #fff;
    border-color: var(--color-primary);
}

.savetolistsbutton--active svg {
    /* Ensure the icon picks up the white color. */
    color: #fff;
}

/* Counter pill inside the button. Shown only when the book is in
   1+ custom lists; hidden via the `hidden` attribute otherwise.

   Styling matches .booklisttabcount on /mybooks/ tabs so users
   recognize the pattern. We also flip background/color when the
   button is in its active state — primary green button needs a
   white pill, white button needs a primary green pill. */

.savetolistsbutton__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.5em;
    padding: 0.1rem 0.4rem;
    border-radius: 0.5em;
    font-size: 0.75rem;
    font-weight: bold;
    line-height: 1;
    background: var(--color-primary);
    color: #fff;
    margin-left: 0.25rem;
    /* Slight vertical offset so the pill aligns optically with the
       button text rather than the cap height. */
    transform: translateY(-1px);
}

.savetolistsbutton__count[hidden] {
    display: none;
}

/* When the button is active (primary green background), invert the
   pill so it stays visible against the colored background. */
.savetolistsbutton--active .savetolistsbutton__count {
    background: #fff;
    color: var(--color-primary);
}

/* ============================================================
   Active-list header — shown above the control panel on mobile.

   Purpose:
     - Make it obvious which list the user just selected (the tab
       strip can scroll off-screen on mobile, leaving only the
       control panel and books visible).
     - Provide a visual anchor for the smooth-scroll-on-tab-tap
       behavior, so the page lands somewhere meaningful.

   Hidden on desktop because the active tab is already adjacent
   to the books and the visual "this is selected" feedback is
   delivered by the tab's `.active` styling.
   ============================================================ */

.booklistactiveheader {
    /* Hidden by default — only shown at the mobile breakpoint
       (see media query below). */
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    margin: 0.5rem 0 0.4rem 0;
    padding-top: 0.75rem;
    /* Subtle separator above the title acts as a visual break
       between the tab strip and the active list view. Helps the
       user perceive "I've chosen one of these and now I'm seeing
       its contents below." */
    border-top: 1px solid var(--color-border);
    /* Smooth-scrolled into view on tab tap; this margin gives the
       header some breathing room from the top of the viewport
       so it doesn't sit flush against the device's address bar
       or notch. */
    scroll-margin-top: 40px;
}

.booklistactiveheader__title {
    margin: 0;
    font-size: 1.75rem;
    font-weight: 700;
    color: var(--color-text);
    line-height: 1.2;
    /* Allow long titles to wrap to a second line rather than
       overflowing the row. */
    word-break: break-word;
    flex: 1;
    min-width: 0;
}

/* ---------- Inline privacy badge ---------- */

.booklistactiveheader__badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.15rem 0.5rem;
    border-radius: 1em;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    flex-shrink: 0;
    line-height: 1.2;
    /* Slight nudge down so the badge sits optically aligned with
       the H2's baseline rather than its top. */
    transform: translateY(-1px);
}

.booklistactiveheader__badge[hidden] {
    display: none;
}

.booklistactiveheader__badge svg {
    width: 0.85rem;
    height: 0.85rem;
}

/* Per-state colors — muted, contextual. Match the privacy-pill
   palette so the affordance reads consistently across the page. */
.booklistactiveheader__badge--unlisted {
    background: #fef6e7;
    color: #8a5a00;
}

.booklistactiveheader__badge--private {
    background: #fde7e7;
    color: #8a0000;
}

/* ---------- Inline privacy badge ---------- */

.booklistactiveheader__badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.15rem 0.5rem;
    border-radius: 1em;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    flex-shrink: 0;
    line-height: 1.2;
    /* Slight nudge down so the badge sits optically aligned with
       the H2's baseline rather than its top. */
    transform: translateY(-1px);
}

.booklistactiveheader__badge[hidden] {
    display: none;
}

.booklistactiveheader__badge svg {
    width: 0.85rem;
    height: 0.85rem;
}

/* Per-state colors — muted, contextual. Match the privacy-pill
   palette so the affordance reads consistently across the page. */
.booklistactiveheader__badge--public {
    background: #e7f4ec;
    color: #1f6b3a;
}

.booklistactiveheader__badge--unlisted {
    background: #fef6e7;
    color: #8a5a00;
}

.booklistactiveheader__badge--private {
    background: #fde7e7;
    color: #8a0000;
}

/* ============================================================
   Two small mobile UX additions:

     1. .booklistactionsrow — wraps share button + "..." menu so
        they sit side-by-side on mobile instead of stacking.
     2. .booklistempty — placeholder shown when a list has no
        books, so the user sees an explanation rather than a void.
   ============================================================ */

/* ---------- Share + menu row ---------- */

/* Desktop: the row is just a transparent flex container that
   passes its children through to the parent control panel's
   layout. We don't want the wrapper to introduce any visual
   change — share button and menu should sit next to each other
   exactly as they did before. */
.booklistactionsrow {
    display: inline-flex;
    align-items: stretch;
    gap: 0.5rem;
    flex-shrink: 0;
}

/* ---------- Empty state ---------- */

.booklistempty {
    margin: 0.5rem 0 1rem 0;
    padding: 1.5rem 1rem;
    /* Dashed border signals "this is a placeholder where content
       would go" — a familiar pattern from drag-and-drop targets,
       database-style placeholders, etc. The dashed treatment is
       softer than a solid border and reads as "not-yet-populated"
       rather than as a UI element you can interact with. */
    border: 1.5px dashed var(--color-border);
    border-radius: 0.6rem;
    text-align: center;
    background: #fff;
}

.booklistempty__message {
    margin: 0;
    color: var(--color-muted);
    font-size: 0.95rem;
    line-height: 1.4;
    /* Cap the line length so the empty-state message reads
       comfortably even on wide viewports — long lines of muted
       centered text get tiring. */
    max-width: 32rem;
    margin-left: auto;
    margin-right: auto;
}

/* ============================================================
   Book card actions: per-card "..." menu + undo toast.

   Three components:
     1. .booklistbookmenu__button — the small ⋯ button on each
        card (top-right of the card body).
     2. .booklistbookmenu — the small popover menu that opens
        from that button.
     3. .booktoast — the bottom-of-screen toast for action +
        undo confirmations. Reusable for any "did a thing,
        offer to undo" UI.
   ============================================================ */

/* ---------- Per-card menu button ---------- */

/* The card needs to be a positioning context so the ⋯ button
   can sit absolutely in its top-right corner without scrolling
   away with the card's contents. */
.booklistbook {
    position: relative;
}

.booklistbookmenu__button {
    position: absolute;
    top: 0.25rem;
    right: 0.25rem;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: none;
    background: rgba(255, 255, 255, 0.85);
    color: var(--color-muted);
    border-radius: 0.4rem;
    font-size: 1rem;
    font-weight: bold;
    line-height: 1;
    cursor: pointer;
    /* Initially translucent — visible but not loud. Becomes more
       prominent on hover/focus or when the menu is open. */
    opacity: 0.6;
    transition: opacity 0.15s, background 0.15s, color 0.15s;
    z-index: 2;
    /* Center the ⋯ glyph since browsers position it inconsistently. */
    display: flex;
    align-items: center;
    justify-content: center;
}

.booklistbook:hover .booklistbookmenu__button,
.booklistbookmenu__button:focus,
.booklistbookmenu__button[aria-expanded="true"] {
    opacity: 1;
    background: #fff;
    color: var(--color-primary);
    outline: none;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}

/* On touch devices, hover doesn't exist — keep the button
   visible at full opacity by default. */
@media (hover: none) {
    .booklistbookmenu__button {
        opacity: 0.85;
    }
}

/* ---------- Per-card menu popover ---------- */

.booklistbookmenu {
    position: absolute;
    top: 2.25rem;
    right: 0.25rem;
    z-index: 10;
    min-width: 9.5rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
    padding: 0.25rem;
}

.booklistbookmenu__item {
    display: block;
    width: 100%;
    background: none;
    border: none;
    padding: 0.5rem 0.75rem;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.875rem;
    color: var(--color-text);
    border-radius: 0.3rem;
    transition: background 0.1s, color 0.1s;
}

.booklistbookmenu__item:hover,
.booklistbookmenu__item:focus {
    background: var(--color-background);
    outline: none;
}

.booklistbookmenu__item--danger {
    color: #c00;
}

.booklistbookmenu__item--danger:hover,
.booklistbookmenu__item--danger:focus {
    background: #fff5f5;
    color: #c00;
}

/* ---------- Toast ---------- */

.booktoast {
    position: fixed;
    left: 50%;
    bottom: 1.25rem;
    transform: translate(-50%, 0.5rem);
    /* Translate-up + opacity transition for the entrance. */
    z-index: 1000;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 0.75rem 0.6rem 1rem;
    background: var(--color-text);
    color: #fff;
    border-radius: 0.5rem;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
    font-size: 0.9rem;
    line-height: 1.3;
    /* Cap width so long messages wrap rather than overflowing
       the viewport. */
    max-width: min(28rem, calc(100vw - 2rem));
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s, transform 0.2s;
}

.booktoast[hidden] {
    display: none;
}

.booktoast--visible {
    opacity: 1;
    pointer-events: auto;
    transform: translate(-50%, 0);
}

.booktoast__message {
    flex: 1;
    min-width: 0;
}

.booktoast__action {
    background: none;
    border: 1px solid rgba(255, 255, 255, 0.4);
    color: #fff;
    padding: 0.3rem 0.7rem;
    border-radius: 0.3rem;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    flex-shrink: 0;
    transition: background 0.1s, border-color 0.1s;
}

.booktoast__action:hover,
.booktoast__action:focus {
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.6);
    outline: none;
}

.booktoast__action[hidden] {
    display: none;
}

.booktoast__close {
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.7);
    font-size: 1.25rem;
    line-height: 1;
    padding: 0.2rem 0.4rem;
    cursor: pointer;
    flex-shrink: 0;
    border-radius: 0.3rem;
    transition: color 0.1s, background 0.1s;
}

.booktoast__close:hover,
.booktoast__close:focus {
    color: #fff;
    background: rgba(255, 255, 255, 0.1);
    outline: none;
}

/* ---------------------------------------------------------------------------
   Blog listing enhancements
   Append to style.css. Uses existing site CSS variables; no new ones needed.
   --------------------------------------------------------------------------- */

/* Category nav strip — sits below the h1 on /blog/ and category pages.
   Wraps on narrow screens; no horizontal scroll. */
.blogcategorynav {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0 0 1.25rem 0;
    padding: 0;
}

.blogcategorynav__pill {
    display: inline-block;
    padding: 0.35em 0.85em;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: #fff;
    color: var(--color-text);
    font-size: 0.85rem;
    text-decoration: none;
    line-height: 1.3;
    transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

.blogcategorynav__pill:hover {
    background: var(--color-tertiary-light);
    border-color: var(--color-tertiary);
    color: var(--color-tertiary-dark);
}

.blogcategorynav__pill.is-active {
    background: var(--color-tertiary);
    border-color: var(--color-tertiary);
    color: #fff;
}

.blogcategorynav__pill.is-active:hover {
    background: var(--color-tertiary-dark);
    color: #fff;
}

/* Per-card meta row: date + category tag, sits between the title and the body */
.blogitem__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
    margin: 0.2rem 0 0.6rem 0;
    font-size: 0.8rem;
    color: var(--color-muted);
}

.blogitem__date {
    color: var(--color-muted);
}

/* Category tag on a card — visually consistent with .blogcategorytag
   used on the single-post view, but smaller and inline-friendly. */
.blogitem__cat {
    display: inline-block;
    padding: 0.15em 0.6em;
    background: var(--color-background-dark);
    border: 1px solid var(--color-border);
    border-radius: 0.25em;
    color: var(--color-muted);
    font-size: 0.75rem;
    text-decoration: none;
    line-height: 1.5;
    transition: background 0.12s ease, color 0.12s ease;
}

.blogitem__cat:hover {
    background: var(--color-tertiary-light);
    color: var(--color-tertiary-dark);
}

/* ============================================================
   "Recommended for you" rail (logged-in homepage).
   Reuses .home__trending / .trendingcard markup but overrides
   the grid to be denser and the typography to be smaller, so
   the rail feels like a recommendation strip rather than a
   feature billboard.
   ============================================================ */

/* Desktop: 8 columns instead of 6. Same 2/3 aspect ratio keeps
   covers undistorted, but each card is narrower so the overall
   rail height drops. */
.home__recommended .home__trendinggrid {
    grid-template-columns: repeat(8, 1fr);
    gap: 1rem;
}

.home__recommended {
    /* Slightly tighter padding than the logged-out Trending Now
       block, since the rail lives inside a busier page. */
    padding: 1.5rem;
    /* Rail can render in two positions on /:
        a) above the feed (short / empty feed), where it's a sibling
           of .home__feed and needs its own bottom spacing;
        b) interleaved inside .home__feed (5+ feed items), where
           the parent's `gap: 1rem` already handles spacing.
       Default to (a) here and override (b) below. */
    margin-bottom: 1rem;
}

/* In the interleaved case the rail is a flex child of .home__feed
   and `gap` already produces the 1rem spacing on both sides. Adding
   margin-bottom in flex would stack on top of gap and create a
   2rem gap below the rail only — visibly inconsistent with the
   1rem gap between every other pair of feed items. */
.home__feed > .home__recommended {
    margin-bottom: 0;
}

.home__recommended .trendingcard__title {
    font-size: 0.8rem;
    /* Two-line clamp, down from three. Recommendation titles
       are short -- author-matched books rarely have subtitles
       as long as the NYT bestseller list does. */
    -webkit-line-clamp: 2;
}

.home__recommended .trendingcard__author {
    font-size: 0.72rem;
}

.home__recommended .trendingcard__body {
    margin-top: 0.45rem;
}

/* =========================================================================
   About page
   --------------------------------------------------------------------------
   New layout for /about/. Built on the existing design tokens
   (--color-primary, --color-secondary, Libre Baskerville for serif
   headings) and reusing the visual patterns already in use elsewhere
   on the site: white rounded cards, primary-coloured kickers in
   uppercase letter-spacing, and a 2px primary accent border on
   profile-style cards (see .userprofileblog for prior art).

   Namespace: .about__* for page-level pieces, .teamcard for the
   reusable team-member card pattern.
   ========================================================================= */

/* Kicker — small uppercase label that introduces a section.
   Matches the pattern used in .userprofileblog__kicker elsewhere. */

.about__kicker {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--color-primary);
    margin: 0 0 0.5rem 0;
}

/* Stat strip — three small cards under the hero. Auto-fit grid so
   they wrap gracefully on narrow viewports. */

.about__stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: 1rem;
    margin: 1rem 0 1.5rem 0;
}

.about__stat {
    background: #fff;
    border: 1px solid var(--color-border);
    border-bottom: 2px solid var(--color-secondary);
    border-radius: 0.75rem;
    padding: 1rem 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.about__statvalue {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.5rem;
    color: var(--color-primary);
    line-height: 1.1;
}

.about__statlabel {
    font-size: 0.8rem;
    color: var(--color-muted);
    line-height: 1.4;
}

/* Story / generic section card. Reused for "Our story" and any
   future single-card section we add. */

.about__story,
.about__team {
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 1rem;
    padding: 1.5rem;
    margin-bottom: 1.5rem;
}

.about__sectiontitle {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.5rem;
    color: var(--color-primary);
    margin: 0 0 1rem 0;
    line-height: 1.25;
}

/* Page-opening title — sized up since it acts as the page's h1.
   Sits at the top of the Our Story section in place of the
   hero text that used to live in the .abouthero band. */
.about__sectiontitle--page {
    font-size: 2rem;
}

.about__lede {
    font-size: 1.05rem;
    line-height: 1.55;
    color: var(--color-text);
    margin: 0 0 1rem 0;
    max-width: 38rem;
}

.about__story p {
    font-size: 1rem;
    line-height: 1.65;
    margin: 0 0 0.85rem 0;
}

.about__story p:last-child {
    margin-bottom: 0;
}

/* Team grid — two-up on desktop, single column on tablet/mobile.
   1fr 1fr is fine here because both cards are equally weighted. */

.about__teamgrid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.25rem;
}

.teamcard {
    display: flex;
    flex-direction: column;
    background: var(--color-background);
    border: 1px solid var(--color-border);
    border-bottom: 2px solid var(--color-primary);
    border-radius: 0.75rem;
    padding: 1.25rem;
    gap: 1rem;
}

.teamcard__portraitwrap {
    /* Decorative ring around the portrait — uses the secondary
       (warm orange) tint to add a hint of colour against all the
       green. Kept subtle: 2px ring, not a heavy frame. Now also
       acts as a link to the team member's user profile, so we
       reset link styling: no underline on hover, block layout. */
    display: block;
    width: 140px;
    height: 140px;
    border-radius: 50%;
    padding: 4px;
    background: linear-gradient(135deg, var(--color-secondary) 0%, var(--color-primary) 100%);
    flex-shrink: 0;
    transition: transform 0.15s, box-shadow 0.15s;
}

.teamcard__portraitwrap:hover {
    text-decoration: none;
    transform: scale(1.03);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.teamcard__portrait {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
    display: block;
    background: #fff;
}

.teamcard__body {
    flex: 1;
    min-width: 0;
}

.teamcard__role {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: bold;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--color-secondary-dark);
    background: var(--color-secondary-light);
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    margin-bottom: 0.5rem;
}

.teamcard__name {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.3rem;
    color: var(--color-primary);
    margin: 0 0 0.6rem 0;
    line-height: 1.2;
}

.teamcard__name a,
.teamcard__name a:visited {
    color: var(--color-primary);
    text-decoration: none;
}

.teamcard__name a:hover {
    text-decoration: underline;
}

.teamcard__bio {
    font-size: 0.95rem;
    line-height: 1.6;
    margin: 0 0 0.75rem 0;
    color: var(--color-text);
}

.teamcard__bio:last-of-type {
    margin-bottom: 0.85rem;
}

.teamcard__socials {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.teamcard__socials li {
    margin: 0;
}

.teamcard__socials a {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.7rem 0.35rem 0.45rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--color-text);
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.teamcard__socials a:hover {
    background: var(--color-primary-light);
    border-color: var(--color-primary);
    color: var(--color-primary);
    text-decoration: none;
}

.teamcard__socials img {
    display: block;
    width: 22px;
    height: 22px;
}

/* Pull-quote — a moment of breathing room before the CTA.
   Big serif quote in primary green with a decorative leading
   quotation mark. */

.about__pullquote {
    margin: 0 0 1.5rem 0;
    padding: 1.75rem 1.5rem 1.5rem;
    background: var(--color-primary-light);
    border-radius: 1rem;
    position: relative;
    overflow: hidden;
}

.about__pullquote::before {
    /* Decorative oversized opening quote, sat behind the text.
       aria-hidden — purely visual. */
    content: "\201C"; /* left double quotation mark */
    position: absolute;
    top: -0.5rem;
    left: 0.75rem;
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 6rem;
    line-height: 1;
    color: var(--color-primary);
    opacity: 0.12;
    pointer-events: none;
}

.about__pullquote blockquote {
    margin: 0;
    padding: 0;
}

.about__pullquote blockquote p {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.3rem;
    line-height: 1.4;
    color: var(--color-primary);
    margin: 0 0 0.75rem 0;
    position: relative;
    z-index: 1;
}

.about__pullquote figcaption {
    font-size: 0.85rem;
    color: var(--color-muted);
    letter-spacing: 0.04em;
}

/* Contact CTA — primary-green card with reversed text. The button
   sits on the right on desktop, drops below on mobile. */

.about__cta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    background: var(--color-primary);
    color: #fff;
    border-radius: 1rem;
    padding: 1.75rem;
    margin-bottom: 1.5rem;
}

.about__ctabody {
    flex: 1;
    min-width: 0;
}

.about__ctabody p {
    margin: 0;
    font-size: 1rem;
    line-height: 1.5;
    opacity: 0.92;
}

/* Modifier versions of kicker/title that read on the dark CTA
   background. */
.about__kicker--onaccent {
    color: var(--color-secondary);
    margin-top: 0;
}

.about__sectiontitle--onaccent {
    color: #fff;
    margin-bottom: 0.4rem;
}

.about__ctabutton {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--color-secondary);
    color: #fff;
    font-weight: 700;
    font-size: 1rem;
    padding: 0.75rem 1.25rem;
    border-radius: 999px;
    flex-shrink: 0;
    transition: background 0.15s, transform 0.15s;
}

.about__ctabutton:link,
.about__ctabutton:visited {
    color: #fff;
}

.about__ctabutton:hover {
    background: var(--color-secondary-dark);
    text-decoration: none;
    transform: translateX(2px);
}

.about__ctabutton svg {
    width: 18px;
    height: 18px;
}

/* ============================================================ */
/* Contact page — uses the about page's card vocabulary          */
/* (.about__stats, .about__story, .about__cta) plus its own      */
/* form-specific bits below.                                     */
/* ============================================================ */

/* Form card. Same surface as .about__story but spaced to give
   the form room to breathe. */
.contact__form {
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 1rem;
    padding: 1.5rem;
    margin-bottom: 1.5rem;
}

.contact__lede {
    font-size: 1.05rem;
    line-height: 1.6;
    color: var(--color-text);
    margin: 0 0 1.25rem 0;
    max-width: 38rem;
}

/* Vertical stack of labelled fields + the actions row. */
.contact__formgrid {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.contact__field {
    display: flex;
    flex-direction: column;
}

.contact__label {
    font-size: 0.8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--color-primary);
    margin-bottom: 0.4rem;
}

/* Inputs sit on the off-white background so they read as input
   against the white card. Focus ring uses the primary green. */
.contact__input,
.contact__textarea {
    font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
    font-size: 1rem;
    color: var(--color-text);
    background: var(--color-background);
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    padding: 0.75rem 0.9rem;
    width: 100%;
    transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}

.contact__textarea {
    min-height: 10rem;
    resize: vertical;
    line-height: 1.55;
}

.contact__input:focus,
.contact__textarea:focus {
    outline: none;
    background: #fff;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-primary-light);
}

/* Errors sit immediately below the field they relate to. The
   non-breaking space placeholder in the markup keeps layout
   stable while empty. */
.contact__field .errormessage {
    margin-top: 0.4rem;
    padding-bottom: 0;
    font-size: 0.9rem;
}

.contact__actions {
    margin-top: 0.25rem;
}

/* Submit "button" is a div (jQuery UI is binding click to #submitbutton),
   so we restyle it to look like the about page's .about__ctabutton —
   same pill, same arrow, same hover lift. */
.contact__submit {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--color-secondary);
    color: #fff;
    font-weight: 700;
    font-size: 1rem;
    padding: 0.75rem 1.4rem;
    border-radius: 999px;
    cursor: pointer;
    user-select: none;
    transition: background 0.15s, transform 0.15s, box-shadow 0.15s;
}

.contact__submit:hover {
    background: var(--color-secondary-dark);
    transform: translateX(2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.contact__submit svg {
    width: 18px;
    height: 18px;
    vertical-align: middle;
    position: relative;
    top: -1px; /* optical centring — SVG middle sits slightly low next to text */
}

/* jQuery UI's .button() call wraps the div and applies its own
   classes. Suppress them so our styling wins. */
.contact__submit.ui-button,
.contact__submit.ui-widget,
.contact__submit.ui-state-default {
    background: var(--color-secondary);
    color: #fff;
    border: none;
    font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
    font-weight: 700;
}

.contact__submit.ui-state-hover,
.contact__submit.ui-state-focus,
.contact__submit.ui-state-active {
    background: var(--color-secondary-dark);
    color: #fff;
    border: none;
}

/* Success state — replaces the form. Same card shell as .contact__form
   so the swap feels seamless. Icon in primary green. */
.contact__success {
    background: #fff;
    border: 1px solid var(--color-border);
    border-bottom: 2px solid var(--color-primary);
    border-radius: 1rem;
    padding: 2rem 1.5rem;
    margin-bottom: 1.5rem;
    text-align: center;
}

.contact__successicon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 4rem;
    height: 4rem;
    border-radius: 50%;
    background: var(--color-primary-light);
    color: var(--color-primary);
    margin-bottom: 1rem;
}

.contact__successicon svg {
    width: 2rem;
    height: 2rem;
}

.contact__success p {
    color: var(--color-muted);
    margin: 0.5rem 0 0 0;
}

/* Contact-details section: same card as .about__story but with the
   three detail cards inside an auto-fit grid like .about__stats. */
.contact__details {
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 1rem;
    padding: 1.5rem;
    margin-bottom: 1.5rem;
}

.contact__detailsgrid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: 1rem;
    margin-top: 0.5rem;
}

.contact__detail {
    background: var(--color-background);
    border: 1px solid var(--color-border);
    border-bottom: 2px solid var(--color-secondary);
    border-radius: 0.75rem;
    padding: 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.contact__detailicon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background: var(--color-primary-light);
    color: var(--color-primary);
}

.contact__detailicon svg {
    width: 1.25rem;
    height: 1.25rem;
}

.contact__detailtitle {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.1rem;
    color: var(--color-primary);
    margin: 0;
    line-height: 1.2;
}

.contact__detailbody {
    font-size: 0.95rem;
    line-height: 1.55;
    color: var(--color-text);
    margin: 0;
    font-style: normal; /* override <address>'s default italic */
}

.contact__socials {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.contact__socials li {
    margin: 0;
}

.contact__socials a {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.75rem 0.4rem 0.5rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--color-text);
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.contact__socials a:hover {
    background: var(--color-primary-light);
    border-color: var(--color-primary);
    color: var(--color-primary);
    text-decoration: none;
}

.contact__socials img {
    display: block;
    width: 22px;
    height: 22px;
}

/* ============================================================
   .viewbookbutton — internal "View Book" button used in legacy
   blog posts after the Phase 2 migration. Visually distinct
   from .affiliatebutton (which is yellow, "buy" coded) -- this
   one reads as a quieter, internal navigation action.
   ============================================================ */

.viewbookbutton {
    background: var(--color-primary-light);
    width: auto;
    padding: 1em;
    color: var(--color-primary);
    border: 1px solid var(--color-primary-light);
    border-radius: 0.25em;
    cursor: pointer;
    font-weight: bold;
    float: left;
    clear: both;
    margin: 1em 0;
}

/* When the button sits inside an <a> (always true after migration),
   inherit our colour treatment rather than the default link colours. */
a:link .viewbookbutton,
a:visited .viewbookbutton {
    color: var(--color-primary);
}

/* Hover/focus state. Important: these rules must come AFTER the
   a:link / a:visited rules above, and target the same selectors,
   so they win on source order and specificity. The original
   .viewbookbutton:hover rule alone would lose to a:link .viewbookbutton
   when the button is wrapped in an <a>, which is always. */
.viewbookbutton:hover,
a:hover .viewbookbutton,
a:focus .viewbookbutton {
    background: var(--color-primary);
    color: #fff;
    border-color: var(--color-primary);
}

/* New-style book insertion writes <a class="viewbookbutton">View Book</a>
   directly (anchor IS the button -- no nested div). The base .viewbookbutton
   rule above already gives it the box styling; these rules cover the link
   state colours that the descendant selectors (a:link .viewbookbutton etc)
   miss when the <a> isn't a parent but the element itself. */
a.viewbookbutton:link,
a.viewbookbutton:visited {
    color: var(--color-primary);
    text-decoration: none;
    /* Anchor is inline by default. Float will block-level it, but
       inline-block keeps padding/borders sensible for any case where
       float gets stripped. */
    display: inline-block;
}

a.viewbookbutton:hover,
a.viewbookbutton:focus {
    color: #fff;
    background: var(--color-primary);
    border-color: var(--color-primary);
}

.searchresults__correction {
    color: var(--muted, #666);
    font-size: 0.95em;
    margin-top: 0.25em;
}
.searchresults__correction strong {
    font-style: italic;
}

/* ===========================================================================
   Phase 4a additions: reading progress card.

   Append to /css/style.css. This is page-level UI for book.php, so it
   lives alongside the other book-page styles rather than in a feature
   stylesheet like discussions.css.

   Colour palette mirrors discussions.css: primary green for active
   reading, secondary orange for accents, plus a coral/warm tone for the
   DNF state (visually distinct from the green "active" state).
   =========================================================================== */


.progresscard {
    background: #fff;
    border-radius: 1rem;
    border: 1px solid var(--color-border);
    border-left: 4px solid var(--color-tertiary);
    padding: 1rem 1.25rem;
    margin: 1.25rem 0;
    transition: border-color 0.2s ease;
}

.progresscard--reading      { border-left-color: var(--color-primary); }
.progresscard--finished     { border-left-color: var(--color-primary); }
.progresscard--dnf          { border-left-color: var(--color-coral); }
.progresscard--not_reading  { border-left-color: var(--color-tertiary); }

.progresscard--pending {
    opacity: 0.7;
    pointer-events: none;
}

.progresscard--justupdated {
    animation: progresscard-pulse 0.8s ease-out;
}

@keyframes progresscard-pulse {
    0%   { background: var(--color-primary-light); }
    100% { background: #fff; }
}


/* ---------- Header ---------- */

.progresscard__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 14px;
    gap: 12px;
    flex-wrap: wrap;
}

.progresscard__title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 1rem;
    font-weight: 500;
    color: var(--color-text);
}

.progresscard__titleicon {
    width: 20px;
    height: 20px;
    color: var(--color-primary);
    flex-shrink: 0;
}

.progresscard--dnf .progresscard__titleicon {
    color: var(--color-coral);
}

.progresscard__meta {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 0.85rem;
    color: var(--color-muted);
}

.progresscard__phrase {
    color: var(--color-muted);
}

.progresscard__dnflink,
.progresscard__editlink,
.progresscard__pickbacklink {
    background: none;
    border: none;
    padding: 0;
    font-family: inherit;
    font-size: 0.8rem;
    cursor: pointer;
    color: var(--color-muted-light);
    text-decoration: underline;
}

.progresscard__pickbacklink {
    color: var(--color-primary);
    font-weight: 500;
}

.progresscard__dnflink:hover,
.progresscard__editlink:hover {
    color: var(--color-text);
}


/* ---------- Bucket grid ---------- */

.progresscard__buckets {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 6px;
}

.progresscard__bucket {
    padding: 8px 4px;
    font-size: 0.8rem;
    font-family: inherit;
    border: 1px solid var(--color-border);
    border-radius: 0.5em;
    background: #fff;
    color: var(--color-muted);
    cursor: pointer;
    line-height: 1.3;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
    text-align: center;
}

.progresscard__bucket:hover {
    background: var(--color-primary-light);
    border-color: var(--color-primary);
    color: var(--color-primary);
}

.progresscard__bucket--active {
    background: var(--color-primary-light);
    border-color: var(--color-primary);
    color: var(--color-primary);
    font-weight: 500;
}


/* ---------- Body (finished / DNF states) ---------- */

.progresscard__bodytext {
    font-size: 0.9rem;
    color: var(--color-text);
    line-height: 1.6;
    margin: 0;
}

.progresscard__restartlink,
.progresscard__wtrlink {
    background: none;
    border: none;
    padding: 0;
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 500;
    cursor: pointer;
    color: var(--color-primary);
    text-decoration: underline;
}

.progresscard__wtrlink {
    color: var(--color-text);
}

.progresscard__restartlink:hover,
.progresscard__wtrlink:hover {
    color: var(--color-primary);
}


/* ---------- Hint ---------- */

.progresscard__hint {
    font-size: 0.75rem;
    color: var(--color-muted-light);
    margin: 10px 0 0;
    line-height: 1.5;
}

/* ===========================================================================
   Phase 4b additions: gated stubs, spoiler pill, override link, composer
   spoiler controls.

   Append to /css/discussions.css.
   =========================================================================== */


/* ---------- Spoiler pill on revealed / past-threshold cards ---------- */

.discussion__spoilerpill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    font-size: 0.7rem;
    font-weight: 500;
    color: var(--color-secondary-dark);
    background: var(--color-secondary-light);
    border-radius: 999px;
    white-space: nowrap;
    line-height: 1.2;
}

.discussion__spoilerpillicon {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
}


/* ---------- Override link in thread / feed header ---------- */

.discussions__overridelink,
.discussionthread__overridebar .discussions__overridelink {
    background: none;
    border: none;
    padding: 0;
    margin-right: 12px;
    font-family: inherit;
    font-size: 0.8rem;
    color: var(--color-secondary-dark);
    text-decoration: underline;
    cursor: pointer;
}

.discussions__overridelink:hover {
    color: var(--color-text);
}

.discussionthread__overridebar {
    text-align: right;
    margin: 0 0 0.5rem;
    padding: 0 4px;
}


/* ---------- Gated feed card ---------- */

.discussioncard--gated {
    background: #fafaf8;
    border-style: dashed;
    padding: 1rem 1.25rem;
}

.discussioncard__gatedheader {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
    flex-wrap: wrap;
}

.discussioncard__gatedlabel {
    font-size: 0.85rem;
    color: var(--color-secondary-dark);
    font-weight: 500;
}

.discussioncard__gatedbody {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.discussioncard__gatedmeta {
    font-size: 0.85rem;
    color: var(--color-muted);
}

.discussioncard__gatedauthor {
    color: var(--color-muted);
}

.discussioncard__gatedtimestamp {
    color: var(--color-muted-light);
}

.discussioncard__revealbutton,
.discussionreply__revealbutton,
.discussiondetail__revealbutton {
    background: var(--color-secondary);
    border: 1px solid var(--color-secondary);
    color: #fff;
    padding: 6px 16px;
    border-radius: 0.5em;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    line-height: 1.2;
}

.discussioncard__revealbutton:hover,
.discussionreply__revealbutton:hover,
.discussiondetail__revealbutton:hover {
    background: var(--color-secondary-dark);
    border-color: var(--color-secondary-dark);
}

.discussioncard__revealbutton:disabled,
.discussionreply__revealbutton:disabled,
.discussiondetail__revealbutton:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}


/* ---------- Gated detail-page OP ---------- */

.discussiondetail--gated {
    background: #fafaf8;
    border-style: dashed;
    border-left-style: solid;
    text-align: center;
    padding: 2rem 1.75rem;
}

.discussiondetail__gatedheader {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    margin-bottom: 1rem;
    flex-wrap: wrap;
}

.discussiondetail__gatedmessage {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, serif;
    font-size: 1.15rem;
    color: var(--color-text);
    margin: 0 0 1.25rem;
    line-height: 1.5;
}

.discussiondetail__gatedactions {
    margin-bottom: 1rem;
}

.discussiondetail__gatedauthor {
    font-size: 0.85rem;
    color: var(--color-muted-light);
    margin: 0;
}


/* ---------- Gated reply ---------- */

.discussionreply--gated {
    background: #fafaf8;
    border-style: dashed;
    padding: 0.75rem 1rem;
}

.discussionreply__gatedheader {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
    flex-wrap: wrap;
    font-size: 0.85rem;
}

.discussionreply__gatedlabel {
    color: var(--color-secondary-dark);
    font-weight: 500;
}

.discussionreply__gatedtimestamp {
    color: var(--color-muted-light);
    font-size: 0.8rem;
}

.discussionreply__gatedbody {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.discussionreply__gatedauthor {
    font-size: 0.85rem;
    color: var(--color-muted);
}

/* ---------- Composer spoiler controls ---------- */

.discussioncomposer__spoilercheckbox,
.replycomposer__spoilercheckbox,
.discussionreply__editspoiler label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.9rem;
    color: var(--color-text);
    cursor: pointer;
}

.discussioncomposer__spoilercheckbox input,
.replycomposer__spoilercheckbox input {
    margin: 0;
}

.discussioncomposer__spoilerthreshold,
.replycomposer__spoilerthreshold,
.discussionreply__editthreshold {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 10px;
    flex-wrap: wrap;
    font-size: 0.85rem;
    color: var(--color-muted);
}

.discussioncomposer__spoilerselect,
.replycomposer__spoilerselect,
.discussionreply__editthresholdselect {
    font-family: inherit;
    font-size: 0.85rem;
    padding: 4px 8px;
    border: 1px solid var(--color-border);
    border-radius: 0.35em;
    background: #fff;
    color: var(--color-text);
}

.replycomposer__spoilerwrap {
    margin-top: 8px;
}

/* ===========================================================================
   Phase 4c: progress card UX polish.

   Three groups of changes (append to /css/style.css):

     1. Compact strip styling for the not_reading / finished / dnf /
        logged-out states.
     2. Affiliate-disclosure restyling -- now a small footnote inside the
        bookcontrolpanel rather than a standalone bordered block.
     3. Booktabs margin tidy -- drop the stale -1px margin-top assumption
        and match the surrounding rhythm.
   =========================================================================== */


/* ---------- Compact progress strip ---------- */

.progresscard--compact {
    background: #fff;
    border-radius: 0.65em;
    border: 1px solid var(--color-border);
    border-left: 4px solid var(--color-tertiary);
    margin: 1.25rem 0;
    padding: 0;
    transition: border-color 0.2s ease;
}

.progresscard--compact.progresscard--finished     { border-left-color: var(--color-primary); }
.progresscard--compact.progresscard--dnf          { border-left-color: var(--color-coral); }
.progresscard--compact.progresscard--not_reading,
.progresscard--compact.progresscard--loggedout    { border-left-color: var(--color-tertiary); }

/* The inner clickable area. For logged-in compact cards this is a
   button (so the whole strip is keyboard-accessible). For logged-out
   the same .compactinner class is used on a plain div with an inline
   link inside; harmless overlap. */
.progresscard__compactinner {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 0.7rem 1rem;
    background: none;
    border: none;
    font-family: inherit;
    font-size: 0.9rem;
    color: var(--color-text);
    text-align: left;
    cursor: pointer;
    line-height: 1.4;
}

.progresscard__compactinner:hover {
    background: var(--color-background);
}

.progresscard--loggedout .progresscard__compactinner {
    cursor: default;
}

.progresscard--loggedout .progresscard__compactinner:hover {
    background: none;
}

.progresscard__compacticon {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    color: var(--color-tertiary);
}

.progresscard--finished .progresscard__compacticon {
    color: var(--color-primary);
}

.progresscard--dnf .progresscard__compacticon {
    color: var(--color-coral);
}

.progresscard__compacticon svg {
    width: 18px;
    height: 18px;
}

.progresscard__compactlabel {
    flex: 1;
    min-width: 0;
}

.progresscard__compactsecondary {
    color: var(--color-muted);
    font-size: 0.85rem;
}

.progresscard__compactchevron {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    color: var(--color-muted-light);
    transition: transform 0.2s ease;
}

.progresscard__compactchevron svg {
    width: 16px;
    height: 16px;
}

.progresscard--expandedopen .progresscard__compactchevron {
    transform: rotate(180deg);
}

.progresscard__compactlink {
    color: var(--color-primary);
    font-weight: 500;
    text-decoration: none;
}

.progresscard__compactlink:hover {
    text-decoration: underline;
}

/* The expandable region revealed beneath the compact strip. The
   server renders this hidden; the JS layer toggles the [hidden]
   attribute. Inside it lives the same header + buckets + hint markup
   as the always-expanded reading card. */
.progresscard__expandable {
    border-top: 1px solid var(--color-border);
    padding: 1rem 1.25rem;
    animation: progresscard-fadein 0.18s ease-out;
}

@keyframes progresscard-fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* When expanded, the compact strip's border-radius needs to flatten
   at the bottom so the expanded area sits cleanly beneath it. */
.progresscard--expandedopen {
    border-bottom-left-radius: 0.65em;
    border-bottom-right-radius: 0.65em;
}


/* ---------- Affiliate disclosure as a footnote in the controlpanel ----- */

/* Phase 4c restyle: the disclosure now lives inside the bookcontrolpanel
   container as a small line of fine print directly under the buy
   buttons. Drop the border, background, and standalone-block styling. */

.bookcontrolpanel .affiliate-disclosure,
.affiliate-disclosure--footnote {
    margin: 0.25rem 0 0;
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
    font-size: 0.7rem;
    line-height: 1.4;
    color: var(--color-muted-light);
    width: 100%;
}

.bookcontrolpanel .affiliate-disclosure a,
.affiliate-disclosure--footnote a {
    color: var(--color-muted-light);
    text-decoration: underline;
}

.bookcontrolpanel .affiliate-disclosure a:hover,
.affiliate-disclosure--footnote a:hover {
    color: var(--color-text);
}


/* ---------- Booktabs margin tidy ---------- */

/* The -1px margin-top assumed the tabs sat flush against the bottom
   of .bookinfomain. They no longer do (progress card sits between
   them). Drop the stale offset and use normal spacing matching the
   progress card's margin. */
.booktabs {
    margin-top: 1.25rem;
}

/* ============================================================
   Phase 9b — Reviews (work-aware) — append to your existing stylesheet
   ============================================================

   Adds three groups of styles:

   1. Header rating summary (.bookrating)
        Under the author line on book.php. Stars + numeric average +
        clickable rating count linking to the Reviews tab.

   2. Overview reviews preview (.bookreviews--preview / .bookreviews__*)
        The compact "top two reviews + see-all link" block that
        replaces the inline full review list on Overview.

   3. Reviews tab pane (.reviewstab / .reviewstab__*)
        Histogram, sort controls, edition filter, pagination.
        Reuses existing .bookreview, .reviewform, .reviewopenbutton
        styles for the list and form themselves.

   Plus a small addition to the per-review .bookreview__date / __edition
   line so the edition hint introduced in this phase has somewhere
   subtle to live.
*/

/* ---------- 1. Header rating summary ---------- */

/* Sits under the author "by ..." line in #bookdetail. Hidden when
   there are no rated reviews (PHP-side gate, not CSS). Vertically
   compact so it doesn't push the rest of the controlpanel down. */
.bookrating {
    display: inline-flex;
    align-items: baseline;
    gap: 0.5rem;
    margin-top: 0.5rem;
    font-size: 0.875rem;
    line-height: 1.2;
}

.bookrating__stars {
    color: var(--color-secondary);
    font-size: 1rem;
    line-height: 1;
    letter-spacing: 0.05em;
    /* Keep stars on one baseline grid even if the row wraps. */
    white-space: nowrap;
}

.bookrating__star {
    color: var(--color-border);
}

.bookrating__star--filled {
    color: var(--color-secondary);
}

/* Half-star: same ★ glyph as every other position (header rating uses
   a single glyph throughout, with colour encoding filled vs unfilled).
   The ::before overlays an orange ★ clipped to the left 50%, on top of
   the parent's grey ★. Identical glyph metrics = pixel-perfect
   alignment. */
.bookrating__star--half {
    position: relative;
    color: var(--color-border);
}

.bookrating__star--half::before {
    content: '★';
    position: absolute;
    left: 0;
    top: 0.1rem; /* optical centering — the half-star glyph sits slightly low next to the full star */
    width: 50%;
    overflow: hidden;
    color: var(--color-secondary);
}

.bookrating__number {
    font-weight: 600;
    color: var(--color-text);
}

.bookrating__count:link,
.bookrating__count:visited {
    color: var(--color-muted);
}

.bookrating__count:hover {
    color: var(--color-primary);
    text-decoration: underline;
}


/* ---------- 2. Overview reviews preview ---------- */

/* The Overview "Reviews" block is now a preview: 0–2 review cards
   plus a footer with a see-all link and a contextual write-link.
   We reuse the existing #bookreviews container, just with a modifier
   class so we can tweak spacing without affecting the full Reviews
   tab pane. */
.bookreviews--preview {
    /* No background — the .bookreview cards inside already have one.
       Just providing structural rhythm to the section. */
}

.bookreviews--preview > h2 {
    margin-bottom: 0.75rem;
}

/* Footer row under the two preview cards. Lays out the see-all link
   on the left and the write-a-review link on the right, with graceful
   stacking on narrow viewports. */
.bookreviews__previewfooter {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 0.75rem;
    padding: 0.5rem 0.25rem 0;
    border-top: 1px solid var(--color-border);
    font-size: 0.875rem;
}

.bookreviews__seeall {
    font-weight: 600;
}

.bookreviews__seeall:link,
.bookreviews__seeall:visited {
    color: var(--color-primary);
}

.bookreviews__seeall:hover {
    color: var(--color-secondary);
}

/* Lower-emphasis pair to the see-all link. The top-bar "Write a
   review" button is the primary CTA; this is a quieter inline echo
   of it positioned at point-of-decision. */
.bookreviews__writelink {
    color: var(--color-muted);
}

.bookreviews__writelink:link,
.bookreviews__writelink:visited {
    color: var(--color-muted);
}

.bookreviews__writelink:hover {
    color: var(--color-primary);
    text-decoration: underline;
}


/* ---------- Per-review edition hint ----------
   Phase 9b: each review card may show a subtle "Reviewed a different
   edition" link when the review's underlying bookid differs from the
   page being viewed. Lives inline on the .bookreview__date line,
   separated by a middot. */

.bookreview__edition-sep {
    color: var(--color-border);
    margin: 0 0.25rem;
}

.bookreview__edition:link,
.bookreview__edition:visited {
    color: var(--color-muted);
    font-style: italic;
}

.bookreview__edition:hover {
    color: var(--color-primary);
    text-decoration: underline;
}


/* ---------- 3. Reviews tab pane ---------- */

.reviewstab {
    margin-top: 1rem;
}

/* Header row: histogram on the left, primary write-action on the right.
   Stacks below 640px (see media-query block at the bottom). */
.reviewstab__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1.5rem;
    padding: 1.25rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    margin-bottom: 1rem;
}

.reviewstab__actions {
    flex: 0 0 auto;
}

/* The actions area reuses .reviewopenbutton (already styled in
   the main reviewform block). Inside the tab header we just want
   to remove the legacy top/bottom margins since the parent already
   provides padding. */
.reviewstab__actions .reviewopenbutton {
    margin: 0;
}

/* ----- Histogram ----- */

.reviewstab__histogram {
    flex: 1;
    display: flex;
    gap: 1.5rem;
    align-items: center;
    min-width: 0;
}

.reviewstab__histogram--empty {
    color: var(--color-muted);
    font-size: 0.875rem;
    align-items: center;
}

.reviewstab__histogram-summary {
    flex: 0 0 auto;
    text-align: center;
    min-width: 5rem;
    padding-right: 1.25rem;
    border-right: 1px solid var(--color-border);
}

.reviewstab__histogram-avg {
    /* Big serif numeral, echoing the H1/H3 type voice on the page. */
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, serif;
    font-size: 2.25rem;
    font-weight: 700;
    line-height: 1;
    color: var(--color-text);
}

.reviewstab__histogram-outof {
    color: var(--color-muted);
    font-size: 1rem;
    margin-left: 0.1rem;
}

.reviewstab__histogram-count {
    margin-top: 0.4rem;
    font-size: 0.75rem;
    color: var(--color-muted);
}

.reviewstab__histogram-bars {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}

.reviewstab__histogram-row {
    display: grid;
    /* label | bar | numeric. Label and numeric are fixed-width so the
       bars all start and end on the same vertical lines regardless of
       the row's count. */
    grid-template-columns: 2rem 1fr 3rem;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.75rem;
    color: var(--color-muted);
}

.reviewstab__histogram-label {
    text-align: right;
    color: var(--color-secondary-dark);
    font-weight: 600;
}

.reviewstab__histogram-bar {
    position: relative;
    height: 0.6rem;
    background: var(--color-background-dark);
    border-radius: 0.3rem;
    overflow: hidden;
}

.reviewstab__histogram-fill {
    display: block;
    height: 100%;
    background: var(--color-secondary);
    border-radius: 0.3rem;
    /* Tiny transition for the case where some future filter changes
       the histogram dynamically. Currently it's PHP-rendered, so
       there's nothing to animate on page load — the transition just
       starts at the target width. */
    transition: width 200ms ease-out;
}

.reviewstab__histogram-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* ----- Sort + edition filter ----- */

.reviewstab__controls {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem;
    margin-bottom: 1rem;
    padding: 0 0.25rem;
    font-size: 0.875rem;
    /* Sort/filter changes navigate to #reviewstabcontrols (a full-page
       reload, since these are GET URLs not in-place JS). The margin
       gives a visual gap above the landed-on element so it doesn't
       hug the viewport's top edge. */
    scroll-margin-top: 1rem;
}

/* Pagination navigates to #bookreviews. Same scroll-margin treatment
   so the review list doesn't hug the top of the viewport after a
   page change. */
#bookreviews {
    scroll-margin-top: 1rem;
}

.reviewstab__sort {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.reviewstab__sort-label {
    /* Override the global `label { font-weight: bold }` — this is more
       of a form-control captioning label than a heavyweight field
       label, so it reads better in regular weight. */
    font-weight: normal;
    color: var(--color-muted);
}

.reviewstab__sort-select {
    /* Tighter than the project's default select padding (0.75em) so
       the controls row stays compact. */
    padding: 0.4em 0.5em;
    font-size: 0.875rem;
    color: var(--color-text);
}

.reviewstab__editionfilter {
    color: var(--color-muted);
    text-align: right;
}

.reviewstab__editionfilter-current {
    color: var(--color-text);
    margin-right: 0.5rem;
}

.reviewstab__editionfilter a:link,
.reviewstab__editionfilter a:visited {
    color: var(--color-primary);
}

/* ----- Pagination ----- */

.reviewstab__pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
    margin: 1.5rem 0 0.5rem;
    padding: 0.75rem;
    font-size: 0.875rem;
}

.reviewstab__pagination-status {
    color: var(--color-muted);
    font-variant-numeric: tabular-nums;
}

.reviewstab__pagination-link {
    padding: 0.4rem 0.85rem;
    border: 1px solid var(--color-border);
    border-radius: 0.4rem;
    background: #fff;
    color: var(--color-primary);
    transition: background-color 150ms ease-out;
}

.reviewstab__pagination-link:link,
.reviewstab__pagination-link:visited {
    color: var(--color-primary);
    text-decoration: none;
}

.reviewstab__pagination-link:hover {
    background: var(--color-primary-light);
    text-decoration: none;
}


/* ============================================================
   Sitewide dialogs and toasts — append to your existing stylesheet.

   Three components, all using existing CSS variables:

   1. .sitedialog       — modal confirmation / alert (native <dialog>).
                          Mirrors .revertowldialog's visual language; the
                          two could be merged in a later cleanup pass.

   2. .sitetoaster      — singleton container for transient notifications.
   3. .sitetoast        — individual toast. Visually echoes .booktoast,
                          but with a generalised API powering it from
                          /js/dialogs.js. The two will likely converge
                          in a follow-up; for now they coexist.
   ============================================================ */

/* ---------- 1. Modal dialog (native <dialog>) ---------- */

.sitedialog {
    border: 1px solid var(--color-border);
    border-radius: 0.5em;
    padding: 1.5rem;
    max-width: 28rem;
    width: calc(100% - 2rem);
    background: #fff;
    color: var(--color-text);
    font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}

.sitedialog::backdrop {
    background: rgba(0, 0, 0, 0.45);
}

.sitedialog__title {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1.25rem;
    font-weight: bold;
    color: var(--color-primary);
    margin: 0 0 0.75rem 0;
}

.sitedialog__body {
    font-size: 0.95rem;
    line-height: 1.45;
    color: var(--color-text);
    margin: 0 0 1.25rem 0;
}

.sitedialog__actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 0.5rem;
}

.sitedialog__button {
    border-radius: 0.5em;
    padding: 0.5rem 1.25rem;
    font-size: 0.95rem;
    cursor: pointer;
    font-family: inherit;
    border: 1px solid var(--color-border);
    background: #fff;
    color: var(--color-muted);
    /* Min width keeps short labels (OK, Yes) from collapsing too thin. */
    min-width: 5rem;
}

.sitedialog__button:hover {
    background: var(--color-background);
    color: var(--color-text);
}

.sitedialog__button--primary {
    background: var(--color-primary);
    color: #fff;
    border-color: var(--color-primary);
    font-weight: bold;
}

.sitedialog__button--primary:hover {
    background: var(--color-secondary);
    border-color: var(--color-secondary);
    color: #fff;
}

/* Destructive variant — coral, for actions like delete / discard.
   Overrides --primary's colour values, so callers can pass both flags
   together (primary + destructive) and get the destructive treatment. */
.sitedialog__button--destructive,
.sitedialog__button--primary.sitedialog__button--destructive {
    background: var(--color-coral);
    border-color: var(--color-coral);
    color: #fff;
}

.sitedialog__button--destructive:hover,
.sitedialog__button--primary.sitedialog__button--destructive:hover {
    background: var(--color-coral-dark);
    border-color: var(--color-coral-dark);
}

.sitedialog__button:disabled {
    background: var(--color-muted-light);
    border-color: var(--color-muted-light);
    color: #fff;
    cursor: not-allowed;
}


/* ---------- 2. Toast container ----------
   The toaster is bottom-centre on desktop, stacking newest at the
   bottom. We rely on flex-direction: column-reverse so a freshly
   appended toast naturally appears above older ones, without us
   having to manage insertion order. */

.sitetoaster {
    position: fixed;
    left: 50%;
    bottom: 1.25rem;
    transform: translateX(-50%);
    z-index: 1000;
    display: flex;
    flex-direction: column-reverse;
    align-items: center;
    gap: 0.5rem;
    /* No background — the container is invisible; only the toasts
       inside it have presence. pointer-events: none so the empty
       area doesn't block clicks underneath; individual toasts
       re-enable it. */
    pointer-events: none;
}


/* ---------- 3. Individual toast ----------
   Visually echoes .booktoast (the existing /mybooks/ undo toast)
   so the two read as the same affordance. Differences are minor:
   .sitetoast lives inside .sitetoaster (flex item), so the position:
   fixed and bottom positioning are on the container instead. */

.sitetoast {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 0.75rem 0.6rem 1rem;
    background: var(--color-text);
    color: #fff;
    border-radius: 0.5rem;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
    font-size: 0.9rem;
    line-height: 1.3;
    max-width: min(28rem, calc(100vw - 2rem));
    /* Entrance: slide up + fade in. Toggled by .sitetoast--visible. */
    opacity: 0;
    transform: translateY(0.5rem);
    pointer-events: none;
    transition: opacity 0.2s, transform 0.2s;
}

.sitetoast--visible {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

/* Success toasts get a subtle green-tinted border accent — keeps the
   dark base so it still reads as "transient notification" rather than
   "page content" but signals the positive outcome. */
.sitetoast--success {
    border-left: 3px solid var(--color-primary);
    padding-left: calc(1rem - 3px);
}

/* Error toasts get a coral accent for the same reason. We don't go
   full red-on-red because that'd compete too hard with the page
   for attention; the toast is meant to be passive feedback. */
.sitetoast--error {
    border-left: 3px solid var(--color-coral);
    padding-left: calc(1rem - 3px);
}

.sitetoast__message {
    flex: 1;
    min-width: 0;
}

.sitetoast__close {
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.7);
    font-size: 1.25rem;
    line-height: 1;
    padding: 0.2rem 0.4rem;
    cursor: pointer;
    flex-shrink: 0;
    border-radius: 0.3rem;
    transition: color 0.1s, background 0.1s;
}

.sitetoast__close:hover,
.sitetoast__close:focus {
    color: #fff;
    background: rgba(255, 255, 255, 0.1);
    outline: none;
}


/* ============================================================
   Phase 9b follow-up — review card pill cluster.
   Two pills, in priority order: "Your review" (primary green)
   and "Different edition" (tertiary slate). Either or both can
   render; layout handles both cases via flex.

   The "Your review" pill paired with the card tint helps the
   eye accept your own review being pinned out of sort order.
   The "Different edition" pill is a navigation link to the
   reviewed edition.
   ============================================================ */

/* Subtle tint on the whole card when it's the viewer's own. Pale
   primary-green ties it to the site's "you" colour language. The
   border picks up the same family so the card still feels
   boundaried, not just floating in tint. */
.bookreview--mine {
    background: var(--color-primary-light);
    border-color: var(--color-primary);
}

/* Pill cluster sits at the top of the body column. Wrap allows
   the second pill to drop below the first on narrow widths
   rather than overflowing. */
.bookreview__pills {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-bottom: 0.4rem;
}

/* Pill base — both variants share the shape. */
.bookreview__pill {
    display: inline-flex;
    align-items: center;
    padding: 0.1rem 0.55rem;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.4;
    text-transform: uppercase;
    /* Anchor variants inherit a:link colour from the global rule
       (var(--color-primary)). Override with #fff so the pill text
       reads correctly on its coloured background. */
    color: #fff;
}

.bookreview__pill--mine {
    background: var(--color-primary);
}

/* "Different edition" — slate-blue (tertiary). Clickable: whole
   pill navigates to the edition this review was written against.
   The cursor + subtle hover lift signal interactivity without
   shouting. */
.bookreview__pill--otheredition {
    background: var(--color-tertiary);
    cursor: pointer;
    transition: background 0.1s ease-in-out;
}

.bookreview__pill--otheredition:link,
.bookreview__pill--otheredition:visited {
    color: #fff;
    text-decoration: none;
}

.bookreview__pill--otheredition:hover,
.bookreview__pill--otheredition:focus {
    background: var(--color-tertiary-dark);
    color: #fff;
    text-decoration: none;
}

/* Cross-edition Edit is rendered as <a> for navigation. The existing
   .bookreview__actions button rules don't cover anchors, so replicate
   the visual treatment here keyed on .reviewedit--navigate. We deliberately
   don't piggyback on the existing button selector so it stays clean. */
a.reviewedit--navigate {
    display: inline-block;
    padding: 0.25rem 0.75rem;
    background: #fff;
    color: var(--color-muted);
    border: 1px solid var(--color-border);
    border-radius: 0.25rem;
    font-size: 0.75rem;
    cursor: pointer;
    font-family: inherit;
    line-height: 1.4;
    text-decoration: none;
}

a.reviewedit--navigate:link,
a.reviewedit--navigate:visited {
    color: var(--color-muted);
    text-decoration: none;
}

a.reviewedit--navigate:hover {
    background: var(--color-background);
    color: var(--color-text);
    text-decoration: none;
}

/* ============================================================
   Phase 9b — Editions tab
   ============================================================

   A flat list of sibling-edition cards. Each card is an <a> with
   a small cover on the left and a stack of conditionally-rendered
   metadata rows on the right. The data is unreliable enough that
   we render only fields that have values, rather than fabricating
   "Publisher: —" rows that look incomplete.
*/

.editionstab {
    margin-top: 1rem;
}

/* Empty state: shown when the work has no other editions. Reads
   as a soft note rather than a broken state. */
.editionstab__empty {
    padding: 1.5rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    color: var(--color-muted);
    font-size: 0.95rem;
    line-height: 1.5;
    text-align: center;
}

.editionstab__heading {
    /* Echoes h2 site convention but a touch lighter — the heading is
       a framing line, not a section divider, since the cards below
       carry their own visual weight. */
    font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--color-text);
    margin: 0 0 1rem;
    line-height: 1.4;
}

.editionstab__heading em {
    /* Italicising titles is the project's convention; <em> renders
       italic by default, and we keep the same colour so it doesn't
       compete with the rest of the heading. */
    color: var(--color-text);
}

.editionstab__list {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}


/* ---------- Edition card ---------- */

.editioncard {
    display: flex;
    gap: 1rem;
    padding: 0.85rem;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 0.5rem;
    text-decoration: none;
    color: inherit;
    transition: border-color 0.15s ease-out, background 0.15s ease-out;
}

.editioncard:link,
.editioncard:visited {
    color: var(--color-text);
    text-decoration: none;
}

.editioncard:hover {
    /* Subtle border tint + slight bg shift on hover. Avoids the
       lift-on-hover transform used by morebyauthor cards — these
       are taller and a lift would feel a bit jumpy with multiple
       cards in column. */
    border-color: var(--color-primary);
    background: var(--color-background);
    text-decoration: none;
}

.editioncard__cover {
    /* Fixed-aspect cover. 5rem wide × 7.5rem tall preserves the
       standard book 2:3 ratio. Flex-shrink: 0 so longer metadata
       rows never compress the cover into a smear. */
    flex-shrink: 0;
    width: 5rem;
    height: 7.5rem;
    border: 1px solid var(--color-border);
    border-radius: 0.3rem;
    overflow: hidden;
    background: var(--color-background);
}

.editioncard__cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Coverless fallback — a neutral panel with a book glyph in muted
   colour. Same dimensions as a real cover so the row height stays
   consistent across the list. */
.editioncard__cover-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-muted-light);
    font-size: 2rem;
    background: var(--color-background);
}

.editioncard__meta {
    flex: 1;
    min-width: 0; /* prevents long ISBNs from forcing horizontal overflow */
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    font-size: 0.875rem;
    line-height: 1.4;
}

/* Title is only rendered when it differs from the page's book title.
   Use the project's serif voice (same as h1) so the eye reads it
   as the card's primary identifier. */
.editioncard__title {
    font-family: 'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
    font-size: 1rem;
    font-weight: 600;
    color: var(--color-primary);
    margin-bottom: 0.3rem;
    line-height: 1.3;
}

.editioncard__row {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}

.editioncard__label {
    flex-shrink: 0;
    width: 5rem;
    color: var(--color-muted);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.editioncard__value {
    flex: 1;
    min-width: 0;
    color: var(--color-text);
    word-break: break-word;
}

.editioncard__value--isbn {
    /* Tabular numerals so the ISBN reads cleanly and doesn't waver
       between columns when several editions stack in the list. */
    font-variant-numeric: tabular-nums;
    font-size: 0.85rem;
    color: var(--color-muted);
}

/* ---------------------------------------------------------------------------
   Booklist sidebar card
   ---------------------------------------------------------------------------
   Standalone card rendered by /booklistsidebar.php into #booklistsidebar.
   Previously this lived inside the .profilebox--loggedin panel; it now sits
   below the profile box as its own card so titles get the full sidebar width.

   Colour story: each row's kind ('status' | 'favorites' | 'custom') drives
   both the icon hue and the count pill background. The data is pre-sorted
   status > favorites > custom in the PHP query, so the rows form three
   coloured bands top-to-bottom without needing explicit section headers.
   --------------------------------------------------------------------------- */

.booklistcard {
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 1rem;
    margin-top: 1rem;
    font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
    font-size: 0.8125rem; /* 13px */
    color: var(--color-text);
    /* Clip the header's dark background to the rounded corners — without
       this the header bleeds square through the card's border-radius. */
    overflow: hidden;
}

/* Dark green title bar. Sits flush with the card edges (no horizontal
   margin) so it reads as a banner, not a styled row. */
.booklistcard__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.625rem 1rem;
    background: var(--color-primary);
    color: #fff;
}

.booklistcard__title {
    font-size: 0.8125rem;
    font-weight: 500;
    color: #fff;
    letter-spacing: 0.02em;
}

/* Slightly muted against the dark green so the title gets visual priority. */
.booklistcard__total {
    font-size: 0.6875rem; /* 11px */
    color: rgba(255, 255, 255, 0.75);
}

/* All non-header content sits inside this body wrapper, which provides
   the inner padding that .booklistcard used to own directly. */
.booklistcard__body {
    padding: 0.5rem 1rem 1rem 1rem;
}

.booklistcard__row {
    display: flex;
    align-items: center;
    gap: 0.5625rem; /* 9px */
    padding: 0.3125rem 0.25rem; /* 5px 4px */
    border-radius: 5px;
    line-height: 1.3;
    /* Anchor reset — rows are <a> elements linking to /mybooks/?list={id}. */
    text-decoration: none;
    color: inherit;
    cursor: pointer;
}

.booklistcard__row:hover {
    background: var(--color-background);
}

.booklistcard__icon {
    width: 17px;
    height: 17px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Align with the first line of a wrapped title rather than the centre
       of a two-line block, which would otherwise drift downward. */
    align-self: flex-start;
    margin-top: 1px;
}

.booklistcard__icon svg {
    width: 17px;
    height: 17px;
}

/* Kind-based icon colours. The icon inherits via stroke="currentColor",
   so we just set `color` here. */
.booklistcard__icon--status    { color: var(--color-primary); }
.booklistcard__icon--favorites { color: var(--color-secondary-dark); }
.booklistcard__icon--custom    { color: var(--color-tertiary); }

.booklistcard__name {
    flex: 1;
    font-size: 0.8125rem;
    color: var(--color-text);
    min-width: 0;
    /* Two-line clamp with ellipsis. Most titles will fit on one line; the
       rare overlong title wraps once and then truncates. The full title
       is always available via the title attribute on hover. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-wrap: break-word;
}

.booklistcard__count {
    font-size: 0.6875rem;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    border-radius: 999px;
    padding: 1px 8px;
    min-width: 22px;
    text-align: center;
    flex-shrink: 0;
    /* Same flex-start logic as the icon — pin to the first line of the
       title rather than vertical-centring against a wrapped block. */
    align-self: flex-start;
    margin-top: 1px;
}

.booklistcard__count--status    { color: var(--color-primary);      background: var(--color-primary-light); }
.booklistcard__count--favorites { color: var(--color-secondary-dark); background: var(--color-secondary-light); }
.booklistcard__count--custom    { color: var(--color-tertiary-dark); background: var(--color-tertiary-light); }

/* Zero count — neutral grey pill, reads as "nothing here yet" without
   shouting. Overrides any kind-specific pill that would otherwise apply. */
.booklistcard__count--zero {
    color: var(--color-muted-light);
    background: var(--color-background-dark);
}

/* Empty-list row: title and icon muted; the count pill is already
   handled by --zero above. */
.booklistcard__row--empty .booklistcard__name {
    color: var(--color-muted-light);
}

.booklistcard__row--empty .booklistcard__icon {
    opacity: 0.5;
}

/* "+ New list" affordance at the bottom of the card. Links through to
   /mybooks/ where the user can actually create one. */
.booklistcard__newlist {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    padding: 0.3125rem;
    margin-top: 0.375rem;
    font-size: 0.75rem;
    color: var(--color-muted-light);
    text-decoration: none;
    border-radius: 5px;
    border: 1px dashed var(--color-border);
}

.booklistcard__newlist:hover {
    border-color: var(--color-primary);
    color: var(--color-primary);
}


/* ============================================================
   Hero cover wall — logged-out homepage.
   Replaces the SVG book art with a 3x3 grid of real NYT-source
   book covers. The grid is taller than the hero's visible area,
   so the bottom row bleeds past the hero's bottom edge and is
   clipped by .home__hero's overflow:hidden — implying "there's
   more here than fits".
   ============================================================ */

.home__heroart--coverwall {
    /* Override the SVG flex-shrink default. The grid container is
       wide enough to host 3 sizeable covers — small covers read as
       "lost" over on the right, larger ones anchor the panel. */
    width: 22rem;
    /* Pull the grid well past the hero's padding-bottom so the
       bottom row is clipped by .home__hero's overflow:hidden. The
       deeper the negative margin, the more pronounced the
       "there's more here than fits" bleed. */
    margin-bottom: -4rem;
    align-self: end;
}

.home__coverwall {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.55rem;
}

.home__coverwallcell {
    position: relative;
    aspect-ratio: 2 / 3;
    overflow: hidden;
    border-radius: 0.25rem;
    /* Soft shadow so each cover reads as a separate object on
       the warm gradient background, not a flat-coloured tile. */
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
    background: var(--color-background);
}

.home__coverwalllink {
    display: block;
    width: 100%;
    height: 100%;
}

.home__coverwallcell img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* ============================================================
   .bookstable — quick-reference table for "books in order"
   blog posts. Built on the site's design tokens so the look
   carries over to other author pages (Patterson, Kava, etc.)
   without further work. Three columns: #, Title, Year.
   ============================================================ */

.bookstable {
    width: 100%;
    border-collapse: collapse;
    margin: 1em 0 1.5em;
    font-size: 0.875rem;
    background: var(--color-background);
    border: 1px solid var(--color-border);
    border-radius: 0.5em;
    overflow: hidden; /* clip striping against the rounded corners */
}

.bookstable thead th {
    background: var(--color-primary-light);
    color: var(--color-primary);
    font-weight: 600;
    text-align: left;
    padding: 0.6em 0.85em;
    border-bottom: 1px solid var(--color-border);
    letter-spacing: 0.02em;
}

.bookstable tbody td {
    padding: 0.45em 0.85em;
    border-bottom: 1px solid var(--color-border);
    vertical-align: top;
}

.bookstable tbody tr:last-child td {
    border-bottom: none;
}

/* Subtle zebra striping using the design system's "dark" page
   background — quiet enough that it doesn't compete with the
   header, strong enough to help row tracking on a 21-row list. */
.bookstable tbody tr:nth-child(even) {
    background: var(--color-background-dark);
}

.bookstable tbody tr:hover {
    background: var(--color-tertiary-light);
}

/* Internal links inherit the brand-green treatment rather than
   the default blue — keeps the table feeling typographic. */
.bookstable a:link,
.bookstable a:visited {
    color: var(--color-primary);
    text-decoration: none;
}

.bookstable a:hover,
.bookstable a:focus {
    text-decoration: underline;
}

/* Narrow numeric columns (#, Year). tabular-nums keeps digits
   aligned vertically — small detail, big quality-of-life win
   on a long table. */
.bookstable th:first-child,
.bookstable td:first-child {
    width: 3em;
    color: var(--color-muted);
    font-variant-numeric: tabular-nums;
}

.bookstable th:last-child,
.bookstable td:last-child {
    width: 4.5em;
    color: var(--color-muted);
    font-variant-numeric: tabular-nums;
}

/* Inline annotation for novellas / short stories, used to fold
   the old "Type" column into the Title column. */
.bookstable .novella-label {
    color: var(--color-muted);
    font-size: 0.85em;
    font-style: italic;
    margin-left: 0.25em;
}



/* ------------------------------------------- Overrides ----------------------------------------------- */
input {
	font-size: 1em;
	padding: 0.75em;
	border: 1px solid var(--color-border);
	border-radius: 0.25em;
	font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
	color: #333;
}

select {
	font-size: 1em;
	padding: 0.75em;
	border: 1px solid var(--color-border);
	border-radius: 0.25em;
	font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
	color: var(--color-muted);
}

h1 {
	font-size: 2em;
	font-family:  'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
	margin-top: 0;
}

h2 {
	font-size: 1.5em;
	font-family: 'Inter', 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
	margin-top: 0;
}

h3 {
	font-size: 1.25em;
	font-family:  'Libre Baskerville', 'Playfair Display', Georgia, 'Times New Roman', Times, serif;
	margin-top: 0;
}

label {
	font-weight: bold;
	color: #333;
}

#gdpr-cookie-message {
    z-index: 9999;
}

/* Tablet: right sidebar becomes drawer */
@media (max-width: 1024px) {
    .layout {
        grid-template-columns: minmax(180px, 240px) 1fr;
    }

    .content {
        padding-top: 4rem;
    }

    .hamburger-right {
        display: flex;
    }

    .overlay-right {
        display: block;
    }

    .sidebar-right {
        position: fixed;
        top: 0;
        right: 0;
        width: 260px;
        max-width: 85vw;
        height: 100vh;
        transform: translateX(100%);
        box-shadow: -2px 0 10px rgba(0,0,0,0.15);
    }

    .sidebar-right.open {
        transform: translateX(0);
    }

    /* Right sidebar is now a drawer; release the footer's right
       offset so its content can use the full width to the viewport
       edge (still capped by .footercontent's max-width). */
    .footer {
        padding-right: 0;
    }

	.bookinforow {
		flex-direction: column;
	}

	.bookinfodetails {
		margin: 1rem 0 0 0;
		width: 100%;
	}

	.profilepage__layout {
        grid-template-columns: 16rem 1fr;
    }

        .home__heroinner {
        /* Stack the hero into a single column from tablet down. In the
           side-by-side layout the fixed-width cover wall ate most of the
           row at tablet / mobile-landscape widths, crushing the text
           column against the left edge. One column gives the text full
           width and drops the wall below it (natural source order). */
        grid-template-columns: 1fr;
        padding: 2rem;
        gap: 1.5rem;
    }

    .home__herotitle {
        font-size: 2rem;
    }

    .home__heroart svg {
        width: 9rem;
    }

    .home__benefitsgrid {
        grid-template-columns: 1fr;
        gap: 1.5rem;
    }

    .home__trendinggrid {
        grid-template-columns: repeat(4, 1fr);
        gap: 1.25rem;
    }

    .home__recommended .home__trendinggrid {
        grid-template-columns: repeat(6, 1fr);
        gap: 0.9rem;
    }

    .about__teamgrid {
        grid-template-columns: 1fr;
    }

    .reviewstab__histogram-summary {
        min-width: 4rem;
        padding-right: 1rem;
    }

    .reviewstab__histogram-avg {
        font-size: 1.875rem;
    }
	
    .home__heroart--coverwall {
        /* Stacked below the text now, so drop the desktop bottom "bleed"
           and add a top gap instead. Span the column (capped) so the
           single row of 6 covers below has room to breathe rather than
           shrinking into a narrow 18rem block. */
        width: 100%;
        max-width: 36rem;
        margin: 1.5rem 0 0;
    }

    .home__coverwall {
        /* 6 covers in a single row at tablet / mobile-landscape. */
        grid-template-columns: repeat(6, 1fr);
        gap: 0.5rem;
    }
}

/* Mobile: left sidebar also becomes drawer ---------------------------------------------------------- */
@media (max-width: 640px) {
    .layout {
        grid-template-columns: 1fr;
    }

    /* ---------- Footer (mobile) ----------
       Left sidebar is now a drawer too, so release the footer's left
       offset. Inside, tighter padding, smaller heading scale, and the
       bottom row stacks rather than splits left/right. */
    .footer {
        padding-left: 0;
    }

    .footercontent {
        padding: 2rem 1.25rem 1.25rem;
    }

    .footercolumns {
        gap: 1.75rem;
        margin-bottom: 1.5rem;
    }

    .footercolumn__heading {
        font-size: 0.95rem;
    }

    .footerbottom {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.75rem;
    }

	.userprofile__header {
        flex-direction: column;
        align-items: center;
        text-align: center;
    }

    .userprofile__stats {
        justify-content: space-around;
    }

    .hamburger-left {
        display: flex;
    }

    .overlay-left {
        display: block;
    }

    .sidebar-left {
        position: fixed;
        top: 0;
        left: 0;
        width: 260px;
        max-width: 85vw;
        height: 100vh;
        transform: translateX(-100%);
        box-shadow: 2px 0 10px rgba(0,0,0,0.15);
    }

    .sidebar-left.open {
        transform: translateX(0);
    }

	.mobilelogo {
		display: block;
		height: 0rem;
	}

	.bookinforow {
		flex-direction: column;
	}

	.bookinfodetails {
		margin: 1rem 0 0 0;
		width: 100%;
	}

	    .profilepage__layout {
        grid-template-columns: 1fr;
    }

    .profilepage__sidebar {
        position: static;
    }

    .profilesavebar {
        justify-content: stretch;
    }

    .profilesavebar__button {
        width: 100%;
    }

	    .authpage {
        padding: 1rem 0.5rem;
    }

    .authcard {
        padding: 1.5rem;
    }

    .authcard__title {
        font-size: 1.5rem;
    }

    .authform__field-row {
        grid-template-columns: 1fr;
        gap: 0;
    }

    .profilesavebar {
        flex-direction: column;
        align-items: stretch;
        gap: 0.5rem;
    }

    .profilesavebar__error {
        text-align: center;
        margin-right: 0;
    }

    /* The signup banner is mobile-only: warm gradient, primary
       text, arrow on the right. Static (not sticky). */
    .mobilesignupbanner {
        display: flex;
        align-items: center;
        justify-content: space-between;
        background: linear-gradient(
            90deg,
            #fff7eb 0%,
            #ffe9c9 50%,
            #f9d59a 100%
        );
        color: var(--color-primary);
        padding: 0.75rem 1rem;
        font-size: 0.9rem;
        font-weight: bold;
        text-decoration: none;
        border-bottom: 1px solid rgba(0, 0, 0, 0.05);
        margin-top: 4rem; /* clear the fixed hamburger area */
    }

    .mobilesignupbanner:link,
    .mobilesignupbanner:visited {
        color: var(--color-primary);
    }

    .mobilesignupbanner:hover {
        text-decoration: none;
        background: linear-gradient(
            90deg,
            #ffeed5 0%,
            #ffd8a8 50%,
            #f3c787 100%
        );
    }

    .mobilesignupbanner__arrow {
        font-size: 1.1rem;
    }

    .mobilesignupbanner ~ .layout .content {
            padding-top: 1rem;
    }

    /* The .content padding-top from the existing tablet block already
       provides clearance for the hamburger. Cancel that here so the
       banner sits flush under the hamburger area, then the content
       gets a smaller top padding. */
    .content {
        padding-top: 4rem;
    }

    /* Hero on mobile: stack the art below the text. Then either
       hide the art entirely or shrink it — I've kept it shown but
       smaller for a touch of visual interest above the fold. */
    .home__heroinner {
        grid-template-columns: 1fr;
        padding: 2rem 1.5rem;
        text-align: center;
    }

    .home__herotitle {
        font-size: 1.75rem;
    }

    .home__herolead {
        margin-left: auto;
        margin-right: auto;
    }

    .home__heroactions {
        justify-content: center;
    }

    .home__heroart {
        margin: 0 auto;
        order: -1; /* art above text on mobile */
    }

    .home__heroart svg {
        width: 7rem;
    }

    /* Benefits and reviews — single column on mobile. */
    .home__benefits,
    .home__reviews,
    .home__welcome,
    .home__bottomcta {
        padding: 1.5rem;
    }

    .home__bottomtitle {
        font-size: 1.4rem;
    }

    .home__reviewsgrid {
        grid-template-columns: 1fr;
    }

    .home__welcomeactions {
        flex-direction: column;
    }

    .home__welcomeactions .home__btn {
        width: 100%;
    }

    .feedcard {
        padding: 0.875rem;
    }

    .feedcard--followgroup {
        padding: 0;
    }

    .feedcard--followgroup > summary {
        padding: 0.625rem 0.875rem;
        gap: 0.5rem;
    }

    .feedcard__followgroupitem {
        padding: 0.5rem 0.875rem;
    }

    .feedcard--review .feedcard__reviewbody {
        gap: 0.5rem;
    }

    .feedcard__cover {
        width: 3.5rem;
    }

    .feedcard--news--horizontal {
        flex-direction: column;
    }

    .feedcard--news--horizontal .feedcard__newshero {
        width: 100%;
    }

    .home__welcomesmalltitle {
        font-size: 1.25rem;
    }

    .home__discovergrid {
        grid-template-columns: 1fr;
    }

    .followpage__tab {
        padding: 0.6rem 0.75rem;
        font-size: 0.95rem;
    }

    .followpage__toolbar {
        flex-direction: column;
        align-items: stretch;
    }

    .followpage__search,
    .followpage__sort {
        width: 100%;
    }

    .followpage__sort select {
        width: 100%;
    }

    .followlist__row {
        gap: 0.5rem;
        padding: 0.5rem;
    }

    .followlist__avatar {
        width: 2.5rem;
        height: 2.5rem;
    }

    /* On mobile, the follow button gets a smaller size class to fit. */
    .followlist .followbutton {
        padding: 0.4rem 0.6rem;
        font-size: 0.8rem;
    }

    .userprofile__menu {
        min-width: 11rem;
    }

        .newslist__row {
        flex-wrap: wrap;
    }
    .newslist__actions {
        width: 100%;
        justify-content: flex-end;
    }
    .newsform {
        padding: 1rem;
    }

    .feedcard__newsbody {
        padding: 1rem;
    }
    .feedcard__newsheadline {
        font-size: 1.15rem;
    }

        .userprofilenews {
        gap: 0.75rem;
        padding: 0.75rem;
    }
    .userprofilenews__thumb {
        width: 4.5rem;
        height: 4.5rem;
    }
    .userprofilenews__headline {
        font-size: 0.95rem;
    }

     .newsarticle__body {
        padding: 1.25rem;
    }

    .newsarticle__headline {
        font-size: 1.4rem;
    }

    .newsarticle__lead {
        font-size: 0.95rem;
    }

    .home__newsstripgrid {
        grid-template-columns: 1fr;
    }

    .home__newsstrip {
        padding: 1.5rem;
    }

    /* Trending Now: 3-up on mobile keeps covers small enough
       to feel like thumbnails rather than dominant tiles, and
       gives us a clean 4 rows of 3. */
    .home__trendinggrid {
        grid-template-columns: repeat(3, 1fr);
        gap: 0.75rem;
    }

    .home__trending {
        padding: 1.5rem;
    }

    .trendingcard__title {
        font-size: 0.85rem;
    }

    .trendingcard__author {
        font-size: 0.7rem;
    }

    .newsfilter {
        gap: 0.3rem;
    }

    .newsfilter__chip {
        padding: 0.3rem 0.65rem;
        font-size: 0.8rem;
    }

    .newsarticle__herocaption {
        padding-left: 1.25rem;
        padding-right: 1.25rem;
    }

    .morebyauthor {
        padding: 1rem;
    }

    .morebyauthor__card {
        width: 6.5rem;
    }

    .userprofileblog {
        gap: 0.75rem;
        padding: 0.75rem;
    }

    .userprofileblog__thumb {
        width: 4.5rem;
        height: 4.5rem;
    }

    .userprofileblog__headline {
        font-size: 0.95rem;
    }

    .booklistcontrolpanel {
        flex-direction: column;
        align-items: stretch;
        gap: 0.5rem;
    }

    .booklistcontrolpanel #booklistbookfilter {
        width: 100%;
    }

    /* Hide the "Privacy" label on mobile — the pills themselves
       are self-explanatory and screen real estate is tight. */
    .booklistprivacylabel {
        display: none;
    }

    .booklistprivacygroup {
        align-self: stretch;
        justify-content: space-between;
    }

    .booklistprivacypill {
        flex: 1;
        justify-content: center;
        padding: 0.5rem 0.4rem;
        font-size: 0.8rem;
    }

    .profilelists__grid {
        grid-template-columns: 1fr;
    }

    .profilelistcard {
        padding: 0.875rem;
    }

    .profilelistcard__covers {
        margin-bottom: 0.6rem;
    }

    .booklistpage__header {
        padding: 1.25rem;
    }

    .booklistpage__heading {
        font-size: 1.4rem;
    }

    .booklistpage__icon {
        width: 1.4rem;
        height: 1.4rem;
    }

    .booklistpage__meta {
        gap: 0.5rem;
    }

    .booklistpage__count::before {
        margin-right: 0.5rem;
    }

    .booklistpage__actions {
        flex-direction: column;
        align-items: stretch;
    }

    .booklistpage__actions .followbutton,
    .booklistpage__actions .booksharebutton {
        justify-content: center;
        width: 100%;
    }

    .booklistpage__books {
        grid-template-columns: 1fr;
    }

        .userlistspage__header {
        padding: 1rem;
        gap: 0.75rem;
    }

    .userlistspage__avatar {
        width: 3rem;
        height: 3rem;
    }

    .userlistspage__heading {
        font-size: 1.2rem;
    }

    .profilelists__header {
        align-items: flex-start;
    }

    .profilelists__viewall {
        font-size: 0.8rem;
    }

    .searchresults__title {
        font-size: 1.4rem;
    }

    .searchresult {
        gap: 0.75rem;
        padding: 0.75rem;
    }

    .searchresult__cover {
        width: 4rem;
    }

    .searchresult__title {
        font-size: 1rem;
    }

    /* Hide the chevron on mobile — saves a few pixels of horizontal
       space, and the entire card being tappable is enough affordance. */
    .searchresult__chevron {
        display: none;
    }

    .searchresults__empty {
        padding: 2rem 1.25rem;
    }

        .newlistmodal {
        padding: 0.5rem;
    }

    .newlistmodal__panel {
        max-height: 95vh;
    }

    .newlistmodal__title {
        font-size: 1.1rem;
    }

    .booklisttabspacer {
        width: 0.75rem;
    }

    .booklisttabnew {
        padding: 0.5rem;
    }

    .booklistpage__menu {
        min-width: 11rem;
    }

    .savetolistspopover {
        position: fixed;
        left: 1rem;
        right: 1rem;
        top: auto;
        width: auto;
        max-width: none;
        /* When fixed-positioned, our top: auto inherits from the
           absolute-positioned default of "where it would naturally
           appear in flow", which means just below the button. This
           usually works because the wrap is in normal flow above. */
    }

    .savetolistspopover__body {
        max-height: 14rem;
    }

    /* On mobile the divider needs less horizontal space — the
       whole tab strip is tighter. */
    .booklisttabspacer {
        padding: 0 0.4rem;
    }

    /* The owner menu drops below the rest of the control panel
       when it stacks vertically (which happens at this width
       because the existing breakpoint switches the panel to
       flex-direction: column). Push it back to the right within
       its row by un-stretching it. */
    .booklistcontrolpanel .booklistmenuwrap {
        align-self: flex-end;
        margin-left: 0;
    }

    /* Anchor the menu panel to the right since the wrap is now
       flush right. */
    .booklistmenu {
        min-width: 11rem;
    }

    .booklistgroup__header {
        margin-bottom: 0.4rem;
    }

    .booklistpage__sharenote {
        /* On narrow screens the caption can wrap to two lines;
           give it a touch more line-height so it's still readable. */
        font-size: 0.72rem;
        line-height: 1.35;
    }

    .booklistsharebutton {
        font-size: 0.8rem;
        padding: 0.35rem 0.65rem;
    }

    .booklistsharenote {
        font-size: 0.68rem;
        max-width: 12rem;
    }

    .booklistactiveheader {
        display: flex;
    }

    .booklistempty {
        padding: 1.2rem 0.8rem;
    }

    .booklistempty__message {
        font-size: 0.9rem;
    }

        /* On mobile the parent control panel is flex-direction: column,
       so each child gets its own row. The actions row uses
       internal flex to keep share + menu together on the same row.
       Share button takes available space; menu sits at the right. */
    .booklistactionsrow {
        display: flex;
        align-self: stretch;
        gap: 0.5rem;
        align-items: center;
    }

    /* Share button stretches to fill the available space. */
    .booklistactionsrow .booklistsharebutton {
        flex: 1;
        justify-content: center;
    }

    /* Menu sits at the right at its natural width. The earlier
       mobile rule that pushed it flex-end / margin-left: 0 is
       no longer needed because the new actions row contains it.
       We explicitly reset align-self here in case the old rule
       still exists in the stylesheet (it's harmless to leave). */
    .booklistactionsrow .booklistmenuwrap {
        margin-left: 0;
        flex-shrink: 0;
        align-self: center;
    }

    .booklistbookmenu__button {
        /* Slightly larger touch target on mobile. */
        width: 2rem;
        height: 2rem;
        font-size: 1.1rem;
    }

    .booktoast {
        bottom: 1rem;
        left: 1rem;
        right: 1rem;
        transform: translateY(0.5rem);
        max-width: none;
    }

    .booktoast--visible {
        transform: translateY(0);
    }

    .bookcontent h1 {
        font-size: 1.75rem;
    }

    .bookcontent h1.booktitle--long   { font-size: 1.45rem; }
    .bookcontent h1.booktitle--xlong  { font-size: 1.2rem; }
    .bookcontent h1.booktitle--xxlong { font-size: 1.05rem; }

    /* Book view: keep the action buttons below the cover rather than
       wrapping into the narrow column beside a tall float. The cover is
       float:left; #bookdetail (title/author) still flows beside it.
       Note: when the panel clears a cover taller than #bookdetail, the
       browser's clearance absorbs the panel's top margin (its border edge
       snaps flush to the float's bottom), so margin-top can't create the
       gap. Use padding-top instead -- padding is never eaten by clearance
       -- and zero the margin so the gap stays a consistent 1rem whether
       the panel clears the cover or just follows a taller #bookdetail. */
    .bookcontrolpanel {
        clear: left;
        margin-top: 0;
        padding-top: 1rem;
    }

    .home__recommended .home__trendinggrid {
        grid-template-columns: repeat(4, 1fr);
        gap: 0.6rem;
    }

    .home__recommended {
        padding: 1rem;
    }

    .home__recommended .trendingcard__title {
        font-size: 0.75rem;
    }

    .home__recommended .trendingcard__author {
        font-size: 0.65rem;
    }

        .about__sectiontitle--page {
        font-size: 1.6rem;
    }

    .about__lede {
        font-size: 0.95rem;
    }

    .teamcard__portraitwrap {
        width: 110px;
        height: 110px;
    }

    .about__pullquote blockquote p {
        font-size: 1.1rem;
    }

    .about__cta {
        flex-direction: column;
        align-items: flex-start;
        padding: 1.5rem;
    }

    .about__ctabutton {
        align-self: stretch;
        justify-content: center;
    }

    .about__story,
    .about__team {
        padding: 1.25rem;
    }

    .contact__form,
    .contact__details,
    .contact__success {
        padding: 1.25rem;
    }

    .contact__submit {
        width: 100%;
        justify-content: center;
    }

    .contact__submit:hover {
        /* The translate looks odd on a full-width button. */
        transform: none;
    }

    .progresscard {
        /*padding: 0.875rem 1rem;*/
    }

    .progresscard__header {
        flex-direction: column;
        align-items: flex-start;
        gap: 6px;
    }

    .progresscard__meta {
        width: 100%;
        justify-content: space-between;
    }

    .progresscard__buckets {
        grid-template-columns: repeat(3, 1fr);
    }

    .progresscard__bucket {
        padding: 10px 4px;
        font-size: 0.85rem;
    }

    .discussioncard__gatedbody,
    .discussionreply__gatedbody {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
    }

    .discussiondetail--gated {
        padding: 1.25rem 1rem;
    }

    .discussiondetail__gatedmessage {
        font-size: 1rem;
    }

    .discussionthread__overridebar {
        text-align: left;
    }

    .progresscard__compactinner {
        padding: 0.7rem 0.85rem;
        font-size: 0.85rem;
    }

    .progresscard__compactsecondary {
        font-size: 0.8rem;
    }

    .reviewstab__header {
        flex-direction: column;
        align-items: stretch;
        padding: 1rem;
    }

    .reviewstab__actions {
        /* On mobile the write button gets the full row, which is more
           obviously tappable and reads like a primary CTA. */
        width: 100%;
    }

    .reviewstab__actions .reviewopenbutton {
        width: 100%;
        text-align: center;
    }

    .reviewstab__histogram {
        gap: 1rem;
    }

    .reviewstab__histogram-summary {
        min-width: 3.5rem;
        padding-right: 0.75rem;
    }

    .reviewstab__histogram-avg {
        font-size: 1.625rem;
    }

    .reviewstab__controls {
        flex-direction: column;
        align-items: stretch;
        gap: 0.5rem;
    }

    .reviewstab__editionfilter {
        text-align: left;
    }

    /* The Overview preview footer stacks too — see-all link above,
       write-link below — so neither gets cropped on narrow phones. */
    .bookreviews__previewfooter {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5rem;
    }
	
	    .sitetoaster {
        bottom: 0.75rem;
        /* Allow the container to flex to viewport edges minus margin. */
        width: calc(100% - 1.5rem);
        max-width: calc(100% - 1.5rem);
    }

    .sitetoast {
        width: 100%;
        max-width: none;
    }

    .sitedialog__actions {
        /* Stack the buttons on very narrow screens. */
        flex-direction: column-reverse;
    }

    .sitedialog__button {
        width: 100%;
    }

        .editioncard {
        padding: 0.75rem;
        gap: 0.75rem;
    }

    .editioncard__cover {
        width: 4rem;
        height: 6rem;
    }

    .editioncard__label {
        /* Shrink the label column on phones so values get more room.
           Mobile screens are width-constrained; sacrificing label
           alignment is the right trade. */
        width: 4rem;
        font-size: 0.7rem;
    }

    .editioncard__meta {
        font-size: 0.85rem;
    }

    .editionstab__heading {
        font-size: 1.05rem;
    }
	
    /* Cover wall on mobile: a single row of 4 covers, placed at the
       bottom of the card. The hero stacks to one column at this width
       and .home__heroart gets order:-1 (art above text) by default, so
       we override to order:0 to drop it below the heading and CTAs, and
       reset the desktop bleed. The two-class selector outweighs the
       single-class base rule. */
    .home__heroart--coverwall {
        width: 100%;
        max-width: 22rem;
        margin: 1.5rem auto 0;
        order: 0;
    }

    .home__coverwall {
        grid-template-columns: repeat(4, 1fr);
        gap: 0.4rem;
    }

    /* Show only the first 4 covers on phones; hide the rest. The grid
       still receives all 6 cells from the PHP, so cells 5+ are simply
       suppressed at this width. */
    .home__coverwallcell:nth-child(n+5) {
        display: none;
    }

    .bookstable {
        font-size: 0.8125rem;
    }
    .bookstable thead th,
    .bookstable tbody td {
        padding: 0.4em 0.6em;
    }

} /* End of mobile 640px breakpoint. */

/* =========================================================================
   /books/ — discovery hub (.bd-*)
   Rolled in from the inline <style> block that used to live in
   /books/index.php. Colour tokens come from :root at the top of this file.
   Component classes are prefixed bd- and scoped under .bd-discover so they
   can't collide with anything else. Only the 640px and 1024px breakpoints
   are used (see the two @media blocks at the foot of this section).
   ========================================================================= */
.bd-discover {
	--bd-serif: 'Playfair Display', Georgia, serif;
	--bd-shadow-sm: 0 1px 2px rgba(31, 61, 47, .06);
	--bd-shadow-md: 0 6px 20px rgba(31, 61, 47, .10);
	max-width: 100%;
}
.bd-discover * { box-sizing: border-box; }

/* hero */
.bd-hero {
	background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark));
	border-radius: 18px;
	padding: 42px 44px;
	color: #fff;
	position: relative;
	overflow: hidden;
	margin-bottom: 34px;
	box-shadow: var(--bd-shadow-md);
}
.bd-hero::after {
	content: "";
	position: absolute;
	right: -40px;
	top: -40px;
	width: 280px;
	height: 280px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(229, 161, 93, .30), transparent 62%);
}
.bd-hero__eyebrow {
	font-size: .72rem;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--color-secondary);
	font-weight: 700;
	margin-bottom: 10px;
}
.bd-hero__title {
	font-family: var(--bd-serif);
	font-weight: 700;
	font-size: 2.5rem;
	line-height: 1.08;
	max-width: 16ch;
	margin: 0;
}
.bd-hero__title em { color: var(--color-secondary); font-style: italic; }
.bd-hero__sub {
	margin-top: 14px;
	max-width: 52ch;
	color: rgba(255, 255, 255, .86);
	font-size: 1.02rem;
}
.bd-hero__actions {
	margin-top: 22px;
	display: flex;
	align-items: center;
	gap: 18px;
	flex-wrap: wrap;
	position: relative;
	z-index: 1;
}
.bd-discover .bd-herobtn {
	display: inline-block;
	background: var(--color-secondary);
	color: var(--color-primary-dark);
	font-weight: 700;
	padding: 13px 26px;
	border-radius: 10px;
	text-decoration: none;
	transition: .15s;
	box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
}
.bd-discover .bd-herobtn:hover { background: #fff; transform: translateY(-1px); }
.bd-hero__proof { font-size: .82rem; color: rgba(255, 255, 255, .82); }
.bd-hero__proof a { color: #fff; font-weight: 600; }

/* sections */
.bd-section { margin-bottom: 40px; }
.bd-sechead {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 16px;
	margin-bottom: 14px;
}
.bd-sectitle {
	font-family: var(--bd-serif);
	font-weight: 700;
	font-size: 1.5rem;
	color: var(--color-primary-dark);
	line-height: 1.15;
	margin: 0;
}
.bd-secsub { font-size: .9rem; color: var(--color-muted); margin: 3px 0 0; }
.bd-discover .bd-seeall { font-size: .85rem; font-weight: 600; white-space: nowrap; color: var(--color-primary); text-decoration: none; }

/* rails */
.bd-railwrap { position: relative; }
.bd-rail {
	display: flex;
	gap: 18px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	padding: 6px 2px 14px;
	scrollbar-width: none;
	-ms-overflow-style: none;
}
.bd-rail::-webkit-scrollbar { display: none; }
.bd-rail > * { scroll-snap-align: start; flex: 0 0 auto; }
.bd-railnav {
	position: absolute;
	top: 34%;
	width: 38px;
	height: 38px;
	border-radius: 50%;
	border: 1px solid var(--color-border);
	background: #fff;
	color: var(--color-primary);
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: var(--bd-shadow-md);
	z-index: 3;
	font-size: 1.1rem;
	line-height: 1;
	transition: .15s;
}
.bd-railnav:hover { background: var(--color-primary); color: #fff; }
.bd-railnav--prev { left: -14px; }
.bd-railnav--next { right: -14px; }

/* book card */
.bd-card { width: 152px; position: relative; }
.bd-card__link { display: block; text-decoration: none; }
.bd-card__cover {
	position: relative;
	aspect-ratio: 2 / 3;
	border-radius: 7px;
	overflow: hidden;
	box-shadow: var(--bd-shadow-md);
	background: var(--color-background-dark);
	transition: .18s;
}
.bd-card__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bd-card:hover .bd-card__cover { transform: translateY(-4px); }
.bd-discover .bd-card__title {
	display: block;
	font-weight: 600;
	font-size: .86rem;
	color: var(--color-text);
	margin-top: 10px;
	line-height: 1.25;
	text-decoration: none;
}
.bd-discover .bd-card__title:hover { color: var(--color-primary); }
.bd-card__meta { font-size: .78rem; color: var(--color-muted); margin-top: 4px; display: block; }
.bd-stars { color: var(--color-secondary-dark); letter-spacing: 1px; }
.bd-livedot {
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--color-primary);
	display: inline-block;
	vertical-align: middle;
	margin-right: 4px;
	box-shadow: 0 0 0 0 rgba(43, 84, 66, .5);
	animation: bd-pulse 2.2s infinite;
}
@keyframes bd-pulse {
	0%   { box-shadow: 0 0 0 0 rgba(43, 84, 66, .45); }
	70%  { box-shadow: 0 0 0 7px rgba(43, 84, 66, 0); }
	100% { box-shadow: 0 0 0 0 rgba(43, 84, 66, 0); }
}
.bd-rank {
	position: absolute;
	top: 8px;
	left: 8px;
	z-index: 2;
	width: 30px;
	height: 30px;
	border-radius: 50%;
	background: var(--color-secondary);
	color: var(--color-primary-dark);
	font-weight: 800;
	font-size: .95rem;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 2px 6px rgba(0, 0, 0, .25);
	font-family: var(--bd-serif);
}
.bd-newtag {
	position: absolute;
	top: 9px;
	right: 9px;
	z-index: 2;
	font-size: .6rem;
	font-weight: 700;
	letter-spacing: .05em;
	text-transform: uppercase;
	background: #fff;
	color: var(--color-coral);
	padding: 3px 7px;
	border-radius: 5px;
}

/* genre tiles (name-only now that sub_subject counts are gone) */
.bd-genres { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 14px; }
.bd-genretile {
	border-radius: 12px;
	padding: 18px;
	min-height: 84px;
	display: flex;
	flex-direction: column;
	justify-content: center;
	position: relative;
	overflow: hidden;
	color: #fff;
	text-decoration: none;
	transition: .16s;
	box-shadow: var(--bd-shadow-sm);
}
.bd-genretile:hover { transform: translateY(-3px); box-shadow: var(--bd-shadow-md); }
.bd-genretile__name { font-family: var(--bd-serif); font-weight: 700; font-size: 1.1rem; color: #fff; position: relative; z-index: 1; }
.bd-genretile::after {
	content: "";
	position: absolute;
	right: -22px;
	bottom: -22px;
	width: 90px;
	height: 90px;
	border-radius: 50%;
	background: rgba(255, 255, 255, .10);
}
.bd-g-a { background: var(--color-primary); }
.bd-g-b { background: var(--color-secondary-dark); }
.bd-g-c { background: var(--color-tertiary); }
.bd-g-d { background: var(--color-coral); }
.bd-g-e { background: var(--color-primary-dark); }
.bd-g-f { background: #6d7d97; }

/* reader lists */
.bd-listrow { display: grid; grid-template-columns: repeat(auto-fill, minmax(248px, 1fr)); gap: 18px; }
.bd-listcard {
	background: #fff;
	border: 1px solid var(--color-border);
	border-radius: 12px;
	padding: 16px;
	text-decoration: none;
	transition: .16s;
	box-shadow: var(--bd-shadow-sm);
	display: block;
}
.bd-listcard:hover { transform: translateY(-3px); box-shadow: var(--bd-shadow-md); border-color: var(--color-primary-light); }
.bd-fan { display: flex; margin-bottom: 12px; height: 78px; }
.bd-fan img,
.bd-fan span {
	width: 52px;
	height: 78px;
	border-radius: 5px;
	margin-left: -16px;
	box-shadow: 0 2px 6px rgba(0, 0, 0, .18);
	border: 2px solid #fff;
	object-fit: cover;
	background: var(--color-background-dark);
}
.bd-fan img:first-child,
.bd-fan span:first-child { margin-left: 0; }
.bd-listcard__title { font-family: var(--bd-serif); font-weight: 700; font-size: 1.04rem; color: var(--color-primary-dark); }
.bd-listcard__meta { font-size: .8rem; color: var(--color-muted); margin-top: 5px; }
.bd-listcard__meta b { color: var(--color-tertiary-dark); }

/* editorial / blog */
.bd-editorial { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px; }
.bd-edcard {
	background: #fff;
	border: 1px solid var(--color-border);
	border-radius: 12px;
	overflow: hidden;
	text-decoration: none;
	transition: .16s;
	box-shadow: var(--bd-shadow-sm);
}
.bd-edcard:hover { transform: translateY(-3px); box-shadow: var(--bd-shadow-md); }
.bd-edcard__band { height: 8px; } .bd-edcard__img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; background: var(--color-background-dark); }
.bd-edcard__body { padding: 16px 18px 18px; }
.bd-edcard__kicker { font-size: .66rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--color-secondary-dark); }
.bd-edcard__h { font-family: var(--bd-serif); font-weight: 700; font-size: 1.06rem; color: var(--color-primary-dark); margin: 6px 0 4px; line-height: 1.2; }
.bd-edcard__p { font-size: .85rem; color: var(--color-muted); margin: 0; }

/* CTA strip + join band (logged-out) */
.bd-ctastrip {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
	flex-wrap: wrap;
	background: var(--color-primary-light);
	border: 1px solid #cbdbd1;
	border-radius: 12px;
	padding: 16px 22px;
}
.bd-ctastrip__text { font-size: .95rem; color: var(--color-primary-dark); }
.bd-discover .bd-ctastrip__btn {
	white-space: nowrap;
	font-weight: 700;
	color: var(--color-primary);
	background: #fff;
	border: 1px solid #cbdbd1;
	padding: 9px 18px;
	border-radius: 9px;
	text-decoration: none;
	transition: .15s;
}
.bd-discover .bd-ctastrip__btn:hover { background: var(--color-primary); color: #fff; }
.bd-joinband {
	background: var(--color-secondary-light);
	border: 1px solid #f0d9c4;
	border-radius: 16px;
	padding: 30px 34px;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	flex-wrap: wrap;
}
.bd-joinband__h { font-family: var(--bd-serif); font-weight: 700; font-size: 1.45rem; color: var(--color-primary-dark); }
.bd-joinband__p { font-size: .92rem; color: var(--color-muted); margin: 4px 0 0; }
.bd-discover .bd-btn {
	display: inline-block;
	background: var(--color-primary);
	color: #fff;
	font-weight: 600;
	padding: 12px 26px;
	border-radius: 10px;
	text-decoration: none;
	transition: .15s;
	white-space: nowrap;
}
.bd-discover .bd-btn:hover { background: var(--color-primary-dark); transform: translateY(-1px); }

@media (max-width: 1024px) {
	.bd-hero { padding: 36px 32px; }
	.bd-hero__title { font-size: 2.2rem; }
	.bd-genres { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}

@media (max-width: 640px) {
	.bd-hero { padding: 28px 22px; }
	.bd-hero__title { font-size: 1.9rem; }
	.bd-sectitle { font-size: 1.3rem; }
	.bd-railnav { display: none; }
	.bd-card { width: 132px; }
	.bd-genres { grid-template-columns: repeat(2, 1fr); }
	.bd-listrow,
	.bd-editorial { grid-template-columns: 1fr; }
	.bd-ctastrip,
	.bd-joinband { flex-direction: column; align-items: flex-start; }
}


/* =========================================================================
   /books/ — browse/landing page, explore chips, pager.
   Appended for the subjects-backed discovery work. Still only the 640px and
   1024px breakpoints are used across this stylesheet.
   ========================================================================= */
.bd-browsehead { margin: 4px 0 24px; }
.bd-browsehead__title { font-family: var(--bd-serif); font-weight: 700; font-size: 1.9rem; color: var(--color-primary-dark); margin: 0; line-height: 1.12; }
.bd-browsehead__title em { font-style: italic; color: var(--color-secondary-dark); }
.bd-browsehead__sub { font-size: .9rem; color: var(--color-muted); margin: 6px 0 0; }

.bd-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: 22px 18px; }
.bd-grid .bd-card { width: auto; }

/* explore-by-subject chips (light page background, distinct from hero chips) */
.bd-tags { display: flex; flex-wrap: wrap; gap: 9px; }
.bd-tag {
	font-size: .85rem;
	padding: 7px 14px;
	border-radius: 999px;
	background: #fff;
	border: 1px solid var(--color-border);
	color: var(--color-primary);
	text-decoration: none;
	transition: .15s;
}
.bd-tag:hover { background: var(--color-primary); border-color: var(--color-primary); color: #fff; }

/* pager */
.bd-pager { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 30px; }
.bd-pager__page { font-size: .85rem; color: var(--color-muted); }
.bd-pager__btn {
	font-weight: 600;
	color: var(--color-primary);
	background: #fff;
	border: 1px solid var(--color-border);
	padding: 9px 18px;
	border-radius: 9px;
	text-decoration: none;
	transition: .15s;
}
.bd-pager__btn:hover { background: var(--color-primary); color: #fff; }
.bd-pager__btn[aria-disabled="true"] { opacity: .4; pointer-events: none; }

.bd-empty { color: var(--color-muted); padding: 28px 0; }

@media (max-width: 640px) {
	.bd-grid { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 18px 12px; }
	.bd-browsehead__title { font-size: 1.5rem; }
}