/*
 * Components. Mobile-first: every media query is min-width.
 *
 * The visual language is carried over from the free-books pages — warm
 * off-white ground, white raised surfaces, one navy accent, semantic colour
 * only as tinted pills — so the rebuilt site reads as the same brand.
 */

/* ---- site header ---------------------------------------------------- */
.site-header {
  background: rgba(255, 255, 255, .92);
  backdrop-filter: saturate(1.4) blur(8px);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 20;
}
.site-header .wrap {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 3.5rem;
}
/* The header grows with the logo so the extra height comes from the brand
   rather than from padding the nav apart. */
@media (min-width: 48rem) { .site-header .wrap { min-height: 4.25rem; } }
@media (min-width: 64rem) { .site-header .wrap { min-height: 4.75rem; } }

.site-logo { display: flex; align-items: center; flex: none; }
/* 2rem is right on a phone, where the header is tight and the logo is the
   only thing competing for space. On a laptop that same size reads as
   undersized against a full nav, so it steps up with the viewport. */
.site-logo img { max-height: 2rem; width: auto; }
@media (min-width: 48rem) { .site-logo img { max-height: 2.6rem; } }
@media (min-width: 64rem) { .site-logo img { max-height: 3rem; } }
.site-tagline { display: none; color: var(--text-muted); font-size: var(--fs-sm); }
@media (min-width: 64rem) { .site-tagline { display: block; } }

/* Nav: a horizontally scrollable strip on phones — no hamburger, because the
   item count is small and a visible scrollable row beats a hidden menu. */
.site-nav { margin-left: auto; min-width: 0; }
.site-nav ul {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin: 0; padding: 0; list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.site-nav ul::-webkit-scrollbar { display: none; }
.site-nav a {
  display: block;
  /* Even horizontal padding on every item so the gaps between labels read as
     uniform rather than varying with word length. */
  padding: var(--sp-2) var(--sp-3);
  line-height: 1.4;
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
  font-size: var(--fs-sm);
  font-weight: 550;
  white-space: nowrap;
}
.site-nav a:hover { background: var(--sunken); }
/* Scroll hints (script in ebd_header): the edge with hidden items fades and
   carries an arrow. The fade is a mask, so it works over any background. */
.site-nav { position: relative; }
.site-nav.fade-end ul { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 3rem), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 3rem), transparent); }
.site-nav.fade-start ul { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 3rem), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 3rem), transparent); }
.site-nav.fade-start.fade-end ul {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 3rem, #000 calc(100% - 3rem), transparent);
  mask-image: linear-gradient(to right, transparent, #000 3rem, #000 calc(100% - 3rem), transparent);
}
.nav-more {
  position: absolute; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center;
  width: 1.6rem; height: 1.6rem; padding: 0;
  border: 1px solid var(--border); border-radius: 50%;
  background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm);
  cursor: pointer;
}
.nav-more[hidden] { display: none; }
.nav-more-end { right: -2px; }
.nav-more-start { left: -2px; }
.site-nav a[aria-current="page"] { color: var(--brand); background: var(--sunken); }

/* ---- page furniture -------------------------------------------------- */
main { display: block; padding-block: var(--sp-5) var(--sp-7); }
.page-head { margin-bottom: var(--sp-5); }
.page-head p { color: var(--text-muted); max-width: var(--measure); margin-bottom: 0; }

.breadcrumbs { font-size: var(--fs-sm); color: var(--text-muted); margin-bottom: var(--sp-3); }
.breadcrumbs ol { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: 0; padding: 0; list-style: none; }
.breadcrumbs li + li::before { content: "/"; margin-right: var(--sp-2); color: var(--border); }
.breadcrumbs a { color: var(--text-muted); }

/* ---- cards ----------------------------------------------------------- */
/* The min() is what makes this intrinsically mobile-first: one column when
   the viewport is narrower than the track, without a media query. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 9.5rem), 1fr));
  gap: var(--sp-4);
}
@media (min-width: 48rem) {
  .card-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 11rem), 1fr)); gap: var(--sp-5); }
}

.card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  transition: transform .16s ease, box-shadow .16s ease;
}
@media (hover: hover) {
  .card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }
}
.card-cover {
  width: 100%;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  background: var(--sunken);
}
.card-body { padding: var(--sp-3); display: flex; flex-direction: column; gap: var(--sp-2); flex: 1; }
.card-title {
  font-weight: 600;
  font-size: var(--fs-sm);
  line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.card-author { font-size: var(--fs-xs); color: var(--text-muted); }
.card-foot { margin-top: auto; display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }

/* ---- pills and chips -------------------------------------------------- */
.pill {
  display: inline-block;
  padding: .15em .6em;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .01em;
  white-space: nowrap;
}
.pill-free    { background: var(--free-bg);  color: var(--free-fg); }
.pill-price   { background: var(--price-bg); color: var(--price-fg); }
.pill-warn    { background: var(--warn-bg);  color: var(--warn-fg); }
.pill-neutral { background: var(--sunken);   color: var(--text-muted); }

.chip {
  display: inline-block;
  padding: .2em .65em;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  font-size: var(--fs-xs);
  color: var(--text-muted);
  text-decoration: none;
}
.chip:hover { background: var(--sunken); color: var(--text); }

/* ---- buttons ---------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  min-height: 2.75rem;            /* comfortable touch target */
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--brand);
  color: #fff;
  font: inherit;
  font-weight: 600;
  font-size: var(--fs-sm);
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { background: var(--brand-dark); color: #fff; }
.btn-secondary { background: var(--surface); color: var(--text); border-color: var(--border); }
.btn-secondary:hover { background: var(--sunken); color: var(--text); }
.btn-block { width: 100%; }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .55; pointer-events: none; }

/* ---- flash ------------------------------------------------------------ */
.flash {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: var(--fs-sm);
  margin-bottom: var(--sp-5);
}
.flash-success { background: var(--free-bg);  border-color: #bfe3cb; color: #14532d; }
.flash-warn    { background: var(--warn-bg);  border-color: var(--warn-line); color: var(--warn-fg); }
.flash-error   { background: var(--price-bg); border-color: #f3c3bd; color: var(--price-fg); }

/* ---- pagination -------------------------------------------------------- */
.pagination { display: flex; flex-wrap: wrap; gap: var(--sp-2); justify-content: center; margin-top: var(--sp-6); }
.pagination a, .pagination span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.5rem; min-height: 2.5rem;
  padding-inline: var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  text-decoration: none; color: var(--text);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.pagination a:hover { background: var(--sunken); }
.pagination [aria-current="page"] { background: var(--brand); color: #fff; border-color: var(--brand); }
.pagination .gap { border: 0; background: none; color: var(--text-muted); min-width: 1.5rem; }

/* ---- footer ------------------------------------------------------------ */
.site-footer {
  border-top: 1px solid var(--border);
  background: var(--surface);
  padding-block: var(--sp-6);
  margin-top: var(--sp-8);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.site-footer .wrap { display: grid; gap: var(--sp-5); }
/* h2 for the document outline, sized as the small label it always looked like. */
.footer-heading { font-size: var(--fs-sm); }
@media (min-width: 48rem) { .site-footer .wrap { grid-template-columns: 2fr 1fr 1fr; } }
.site-footer a { color: var(--text-muted); }
.site-footer a:hover { color: var(--brand); }
.footer-links { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }

/* ---- empty state -------------------------------------------------------- */
.empty {
  text-align: center;
  padding: var(--sp-8) var(--sp-4);
  color: var(--text-muted);
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
}

/* ---- book detail --------------------------------------------------------- */
/* One column on phones; the cover only becomes a sticky sidebar once there is
   genuinely room for it. */
.book-detail { display: grid; gap: var(--sp-5); }
.book-detail-cover img {
  width: 100%;
  max-width: 16rem;
  margin-inline: auto;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}
.book-detail h1 { font-size: var(--fs-xl); }
.by-author { color: var(--text-muted); margin-top: calc(var(--sp-2) * -1); }

@media (min-width: 48rem) {
  /* The cover grows with the viewport so it holds its own beside a long
     excerpt; 24rem + a 68ch prose column still fits inside --max-width. */
  .book-detail { grid-template-columns: clamp(17rem, 30vw, 24rem) 1fr; gap: var(--sp-6); align-items: start; }
  .book-detail-cover { position: sticky; top: 4.5rem; }
  .book-detail-cover img { max-width: none; }
  .book-detail h1 { font-size: var(--fs-2xl); }
}

/* Giveaway post: one column, the image whole across the top. */
.giveaway-detail { max-width: 48rem; margin-inline: auto; }
.giveaway-detail-image {
  display: block; width: 100%; height: auto; max-height: 36rem; object-fit: contain;
  background: var(--sunken); border-radius: var(--radius-md); box-shadow: var(--shadow-md);
  margin-bottom: var(--sp-5);
}
.giveaway-kicker { display: flex; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-1);
  font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--brand); }
.giveaway-detail h1 { font-size: var(--fs-xl); }
@media (min-width: 48rem) { .giveaway-detail h1 { font-size: var(--fs-2xl); } }
.giveaway-facts { display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-6); margin: var(--sp-4) 0 0; }
.giveaway-facts dt { font-size: var(--fs-xs); color: var(--text-muted); }
.giveaway-facts dd { margin: 0; font-weight: 650; }

.store-buttons { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-block: var(--sp-5); }
/* A book Amazon no longer sells: the page stays, with this note above the buttons. */
.gone-note {
  margin-block: var(--sp-5) 0;
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--warn-line);
  border-left-width: 4px;
  border-radius: var(--radius);
  background: var(--warn-bg);
  color: var(--warn-fg);
  font-size: var(--fs-sm);
}
.gone-note p { margin: 0; }
.gone-note strong { display: block; margin-bottom: var(--sp-1); font-size: var(--fs-md); }
@media (max-width: 29.99rem) { .store-buttons .btn { width: 100%; } }

.share { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-6); }
.share-label { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); }

/* ---- card media variants ------------------------------------------------- */
/* .card-cover is for real book covers, which are portrait 2:3 (Amazon art).
   .card-media is for WordPress featured images, which on this site are
   landscape — the theme generates 700x325 and 314x160 variants. Forcing those
   into a 2:3 slot crops the title straight off the artwork. */
.card-media {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--sunken);
}

/* ---- chip rows (child categories, tag clouds) ---------------------------- */
.chip-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-5); }
.deal-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }

/* ---- home: hero carousel ------------------------------------------------- */
/*
 * One big image per slide with a caption bar, the shape the site has used for
 * years. The featured images are 3D book mockups sized 700x325 / 1028x520 —
 * landscape and already composed to be shown whole, so the slide matches their
 * aspect and the image is contained, never cropped. Their baked-in white
 * background sits on a white slide, so it reads as one surface.
 */
.hero {
  position: relative;
  margin-bottom: var(--sp-6);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
  background: #fff;
}
.hero-viewport {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}
.hero-viewport::-webkit-scrollbar { display: none; }

.hero-slide {
  position: relative;
  scroll-snap-align: start;
  display: block;
  text-decoration: none;
  color: inherit;
  background: #fff;
  /* The mockups come in a few ratios (700x325 = 2.15, 1028x520 = 1.98), so no
     single box matches them all. A box at 2:1 sits between those, and `cover`
     fills it — crop a few percent of the white margin rather than letterbox
     with white bars down both sides, which is what `contain` was doing. */
  aspect-ratio: 16 / 10;
}
@media (min-width: 48rem) { .hero-slide { aspect-ratio: 2 / 1; } }

/* Generated landscapes are composed centred on the book; the old WordPress
   mockups (below) need nudging up to keep their book in frame. */
.hero-image.is-generated { object-position: center; }

.hero-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Slightly above centre: these mockups place the book high with a reflection
     below, so biasing upward keeps the whole book in frame when cropping. */
  object-position: center 42%;
  display: block;
}

/* Caption bar, like the old slider: title, author, price. Nothing else — the
   artwork is doing the selling. */
.hero-caption {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: linear-gradient(180deg, rgba(14,16,22,0) 0%, rgba(14,16,22,.86) 38%, rgba(14,16,22,.95) 100%);
  color: #fff;
  padding-top: var(--sp-6);
}
@media (min-width: 48rem) { .hero-caption { padding: var(--sp-7) var(--sp-5) var(--sp-4); gap: var(--sp-4); } }
.hero-caption-text {
  min-width: 0;
  font-size: var(--fs-sm);
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
@media (min-width: 48rem) { .hero-caption-text { font-size: var(--fs-md); } }
.hero-caption-text strong { font-weight: 650; }
.hero-caption-by { color: rgba(255,255,255,.75); font-weight: 400; }
.hero-caption .pill { flex: none; margin-left: auto; }

/* The timer, along the hero's top edge — the one place it cannot be missed. */
/* Controls: top-right, where the old slider put its dots, and clear of the
   caption bar so nothing ever overlaps the title. */
/*
 * The controls carry their own surface rather than sitting straight on the
 * artwork. Every slide is a different book cover, so contrast against the
 * background cannot be relied on — dark dots vanished on dark covers. A
 * frosted pill guarantees legibility whatever is behind it.
 */
/*
 * An outline, not a panel.
 *
 * This was a filled translucent pill, and on a phone it read as a white slab
 * dropped on top of the cover — the control was competing with the artwork it
 * was there to navigate. It is now a hairline capsule with nothing inside it.
 *
 * The blur stays. It is not a background: with no fill colour it adds no
 * visible block, it only softens whatever cover art sits underneath so the
 * dots and chevrons keep their edges. Without it the controls would be
 * illegible over a busy or pale cover, which is the failure this pill was
 * originally added to fix.
 */
.hero-controls {
  position: absolute;
  right: var(--sp-2);
  top: var(--sp-2);
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  z-index: 2;
  padding: .25rem .3rem;
  border-radius: var(--radius-pill);
  background: transparent;
  /* Two-tone hairline: a light border with a faint dark ring outside it. A
     single white outline vanishes on a pale cover, and these mockups have a
     white background baked into the top of the artwork, so pale is the common
     case rather than the edge case. */
  border: 1px solid rgba(255, 255, 255, .7);
  box-shadow: 0 0 0 1px rgba(16, 24, 40, .22);
  backdrop-filter: blur(6px);
}

/*
 * White with a shadow rather than white alone: a book cover can be any colour,
 * including white, and a control that disappears on some slides is worse than
 * one that is always slightly heavier than it needs to be.
 */
.hero-nav {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Sized to the glyph, not to the thumb. An earlier version made this box
     2rem so it would be its own tap target, but the buttons are the tallest
     things in the pill — so that padding set the height of the whole control
     and stretched the capsule around a 14px chevron. The hit area is restored
     by ::after below, which costs no layout. */
  width: 1.35rem; height: 1.35rem;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: #fff;
  /* Two shadows: a tight zero-offset one that hugs the stroke as an outline so
     a white chevron still has an edge on a white cover, and a soft offset one
     for depth. A single soft shadow left the glyph reading as pale grey. */
  filter: drop-shadow(0 0 1px rgba(16, 24, 40, .85)) drop-shadow(0 1px 2px rgba(16, 24, 40, .45));
  cursor: pointer;
  padding: 0;
}
.hero-nav svg { width: 14px; height: 14px; }

/* The tap target, decoupled from the drawn circle: an invisible overlay that
   spills outside the button. Shrinking the control visually must not shrink
   what a thumb has to hit, and the pill is small enough that the two targets
   would otherwise be easy to miss between. */
.hero-nav::after {
  content: "";
  position: absolute;
  inset: -.45rem -.3rem;
}

/*
 * Hover is opt-in for pointer devices only.
 *
 * On a touchscreen there is no pointer to leave, so :hover latches after a tap
 * and the arrow keeps a grey disc under it until something else is tapped —
 * which reads as a stuck, oversized button rather than as feedback.
 */
@media (hover: hover) {
  .hero-nav:hover { background: rgba(255, 255, 255, .2); }
}
.hero-nav:focus-visible { background: rgba(255, 255, 255, .25); outline: none; }

.hero-dots { display: flex; gap: var(--sp-1); margin-right: var(--sp-1); }
.hero-dot {
  position: relative;
  width: .5rem; height: .3rem;
  border: 0; padding: 0;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, .55);
  /* The ring is what makes a white dot visible on a white cover. */
  box-shadow: 0 0 0 1px rgba(16, 24, 40, .4);
  cursor: pointer;
  overflow: hidden;
  transition: width .2s ease, background .2s ease;
}
/* The active dot is a DARK track, because the progress bar that sweeps across
   it is white. A light track would leave the countdown invisible on exactly the
   pale covers where it is already hardest to see. */
.hero-dot.is-active {
  width: 1.7rem;
  background: rgba(16, 24, 40, .45);
  /* A WHITE ring on the active dot, where the inactive ones use a dark one.
     The dark track carries its own contrast on a pale cover, but on a dark one
     the track, the ring and the background would all be dark and the dot would
     not exist until the white progress bar had swept part-way across it. */
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .75);
}

/* The active dot fills over exactly the autoplay interval, so the countdown to
   the next slide is visible rather than a surprise. --hero-interval is set by
   the script, so the bar can never drift out of step with the real timer. */
.hero-dot-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  border-radius: inherit;
  /* White, not --brand: the brand blue was chosen to read against the white
     pill that used to sit behind this. Over cover art it is now the darkest
     thing in the control and disappears on dark covers. */
  background: #fff;
}
.hero.is-live .hero-dot.is-active .hero-dot-fill {
  animation: ebdHeroFill var(--hero-interval, 6000ms) linear forwards;
}
/* Paused: the bar freezes where it is, which is the honest signal that the
   timer has stopped rather than merely slowed. */
.hero.is-paused .hero-dot.is-active .hero-dot-fill { animation-play-state: paused; }

@keyframes ebdHeroFill { from { width: 0; } to { width: 100%; } }

/* With motion reduced the bar jumps in steps instead of sweeping, so it still
   communicates progress without a continuously animating element. */
/*
 * These carry information, not decoration, so they opt out of the blanket
 * reduced-motion reset in base.css — which would otherwise collapse them to
 * 0.01ms and leave a permanently-full bar claiming a change is always imminent.
 *
 * They sweep smoothly rather than stepping. An earlier version stepped them to
 * be gentler and it read as stop-motion, which is more distracting than the
 * smooth sweep it replaced.
 */
@media (prefers-reduced-motion: reduce) {
  .hero.is-live .hero-dot.is-active .hero-dot-fill {
    animation-duration: var(--hero-interval, 6000ms) !important;
    animation-timing-function: linear !important;
  }
}

/* The slide transition is driven by scrollTo({behavior:'smooth'}), which the
   blanket reset would force to `auto` (an instant jump). The carousel is
   exempt for the same reason. */
@media (prefers-reduced-motion: reduce) {
  .hero-viewport { scroll-behavior: smooth !important; }
}

/* The phone is the constrained case, so it sets the base size; a wider viewport
   can afford the longer progress bar that makes the countdown readable. */
@media (min-width: 48rem) {
  .hero-controls { right: var(--sp-3); top: var(--sp-3); gap: var(--sp-2); padding: .3rem .45rem; }
  .hero-dot { width: .8rem; height: .35rem; }
  .hero-dot.is-active { width: 2.6rem; }
  .hero-nav { width: 1.6rem; height: 1.6rem; }
  .hero-nav svg { width: 16px; height: 16px; }
}

/* ---- home: layout -------------------------------------------------------- */
.home-layout { display: grid; gap: var(--sp-6); }
@media (min-width: 64rem) {
  .home-layout { grid-template-columns: minmax(0, 1fr) 19rem; gap: var(--sp-7); align-items: start; }
  .home-side { position: sticky; top: 4.5rem; }
}

/* ---- home: the latest-deals list ---------------------------------------- */
/* A list, not a grid: it carries the blurb and price the way the old site did,
   and a book needs its cover big enough to read the title off. */
.deal-list { display: grid; gap: var(--sp-5); }
.deal-row {
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr);
  gap: var(--sp-4);
  padding-bottom: var(--sp-5);
  border-bottom: 1px solid var(--border);
}
.deal-row:last-child { border-bottom: 0; }
@media (min-width: 48rem) {
  .deal-row {
    grid-template-columns: 12rem minmax(0, 1fr);
    gap: var(--sp-5);
    /* Centred against the book, not pinned to the top. The generated portrait
       is 2:3 with breathing room above the book, so at this width it is taller
       than the text beside it — top-aligned, the title started above the book
       and the whole column hung off its upper half. Desktop only: on a phone
       the text runs longer than the thumbnail, and centring would push the
       book down away from its own title. */
    align-items: center;
  }
}
.deal-row-media img {
  width: 100%;
  border-radius: var(--radius);
  background: var(--sunken);
  /* Portrait, because these are Amazon cover images now rather than the
     landscape WordPress mockups — see ebd_listing_cover(). `contain` rather
     than `cover`: cover art is 2:3 only approximately, and cropping a book
     cover shaves the author's name off the bottom. */
  aspect-ratio: 2 / 3;
  object-fit: contain;
  object-position: top;
}
.deal-row-title { font-size: var(--fs-md); margin: 0 0 var(--sp-1); line-height: 1.3; }
@media (min-width: 48rem) { .deal-row-title { font-size: var(--fs-lg); } }
.deal-row-title a { color: inherit; text-decoration: none; }
.deal-row-title a:hover { color: var(--brand); }
.deal-row-body .card-author { margin-bottom: var(--sp-2); }
.deal-row-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin: 0; }

/* ---- home: sidebar ------------------------------------------------------- */
.side-block {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--sp-4);
  margin-bottom: var(--sp-5);
}
.side-title {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-muted);
  margin-bottom: var(--sp-3);
}
.rank-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); counter-reset: rank; }
.rank-list a { display: flex; gap: var(--sp-3); align-items: flex-start; text-decoration: none; color: inherit; }
/* 2:3, the shape of the generated portrait. At 3:4 with object-fit:cover the
   mockup lost its top and bottom — the spine text and the book's corners. */
.rank-list img { width: 3rem; height: 4.5rem; object-fit: contain; border-radius: var(--radius-sm); flex: none; background: var(--sunken); }
.rank-list span { display: block; }
.rank-title { font-size: var(--fs-sm); font-weight: 550; line-height: 1.3; }
.rank-list a:hover .rank-title { color: var(--brand); }

/* ---- listing: hook and excerpt ------------------------------------------- */
/* The editorial shape this site has used since 2012: a bold one-line hook,
   then the blurb. A listing of title + price alone drops the line that
   actually sells the book. */
.deal-hook {
  font-weight: 650;
  margin: 0 0 var(--sp-2);
  color: var(--text);
  line-height: 1.35;
}
.deal-excerpt {
  margin: 0 0 var(--sp-3);
  color: var(--text-muted);
  font-size: var(--fs-sm);
  line-height: 1.55;
}
.more-link { white-space: nowrap; font-weight: 600; }

/* ---- search form ------------------------------------------------------- */
/* Used on /search/ and on the 404 page, where it is the main recovery path
   for a visitor who followed a 13-year-old link. Full width on a phone,
   inline once there is room — the button never wraps under the field on a
   narrow screen, which is where most of this traffic lands. */
.search-form {
  display: flex;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
  max-width: 34rem;
}
.search-form input[type="search"] {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  font: inherit;
  color: var(--text);
}
.search-form input[type="search"]:focus-visible {
  outline: none;
  border-color: var(--brand);
  box-shadow: var(--ring);
}
.search-form .btn { flex: 0 0 auto; }

/* ---- plain link list --------------------------------------------------- */
/* Suggestions on the 404 page and anywhere else a short list of deals needs
   to read as text rather than as cards. */
.link-list { list-style: none; margin: 0 0 var(--sp-5); padding: 0; }
.link-list li {
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border);
}
.link-list li:last-child { border-bottom: 0; }
.link-list a { font-weight: 600; }
.link-list .muted { margin-left: var(--sp-2); font-size: var(--fs-sm); }

/* ---- service / sales pages --------------------------------------------- */
/* Used by /advertise-with-us/ and /premium-book-feature-details/. Mobile-first
   like everything else: every grid below is one column until there is room. */

.lede { max-width: var(--measure); font-size: var(--fs-md); }
.lede p { margin-bottom: var(--sp-4); }

/* Headline numbers. Wraps to 2x2 on a phone rather than shrinking the digits
   to the point where they stop being the thing you notice. */
.stat-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);
  margin: var(--sp-6) 0;
}
.stat {
  padding: var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  text-align: center;
}
.stat-n {
  display: block;
  font-size: var(--fs-xl);
  font-weight: 700;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.stat-l { display: block; margin-top: var(--sp-1); font-size: var(--fs-xs); color: var(--text-muted); }

.reason-grid, .price-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-4);
  margin: var(--sp-5) 0 var(--sp-6);
}
.reason h3 { font-size: var(--fs-md); margin-bottom: var(--sp-2); }
.reason p  { color: var(--text-muted); max-width: var(--measure); }

.price-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}
/* The lead card is marked with a border rather than a colour fill, so it reads
   as emphasis in both the light palette and a high-contrast rendering. */
.price-card-lead { border-color: var(--brand); box-shadow: var(--shadow-md); }
.price-card .pill { align-self: flex-start; }
/* The flag occupies its row in every card and is merely invisible where it does
   not apply, so the three card titles share a baseline. Hiding the card's own
   flag with display:none would shorten that card's header and stagger the row. */
.price-flag[aria-hidden="true"] { visibility: hidden; }
.price-card h3 { font-size: var(--fs-md); margin: 0; }
.price-card p { margin: 0; color: var(--text-muted); }
.price-from { font-size: var(--fs-lg); color: var(--text) !important; }
.price-from strong { color: var(--brand); font-variant-numeric: tabular-nums; }
.price-card .btn { margin-top: auto; text-align: center; }

.price-lines { list-style: none; margin: 0; padding: 0; font-size: var(--fs-sm); }
.price-lines li {
  display: flex; justify-content: space-between; gap: var(--sp-3);
  padding: var(--sp-2) 0; border-bottom: 1px dashed var(--border);
}
.price-lines li:last-child { border-bottom: 0; }

/* Numbered steps and rule lists: a counter rather than list-style so the marker
   can be styled and stays aligned with wrapped text. */
.steps { list-style: none; counter-reset: step; margin: var(--sp-4) 0 var(--sp-6); padding: 0; }
.steps li {
  counter-increment: step;
  position: relative;
  padding: 0 0 var(--sp-4) 2.5rem;
  max-width: var(--measure);
}
.steps li::before {
  content: counter(step);
  position: absolute; left: 0; top: -.1rem;
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.75rem; height: 1.75rem;
  border-radius: var(--radius-pill);
  background: var(--brand); color: #fff;
  font-size: var(--fs-sm); font-weight: 700;
}

.rule-list, .check-list { list-style: none; margin: var(--sp-4) 0 var(--sp-6); padding: 0; }
.rule-list li, .check-list li {
  position: relative; padding: 0 0 var(--sp-3) 1.6rem; max-width: var(--measure);
}
.rule-list li::before { content: "—"; position: absolute; left: 0; color: var(--text-muted); }
.check-list li::before { content: "✓"; position: absolute; left: 0; color: var(--free); font-weight: 700; }

/* Live proof: real covers from the database, scrolled horizontally on a phone
   rather than reflowed into a grid that pushes the CTA off the screen. */
.cover-strip {
  display: flex; gap: var(--sp-3);
  overflow-x: auto;
  padding-bottom: var(--sp-3);
  margin-bottom: var(--sp-6);
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.cover-strip a { flex: 0 0 auto; scroll-snap-align: start; }
.cover-strip img {
  /* A fixed box with object-fit, not `height:auto`: Amazon cover art is
     portrait but not all at one ratio, and letting each image set its own
     height makes the row of them look like a broken grid rather than a shelf. */
  width: 8rem; height: 12rem;
  object-fit: cover;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  background: var(--sunken);
}

/* FAQ. <details> so it works with no JavaScript at all, and so the answers are
   in the DOM for a crawler even while collapsed. */
.faq { margin: var(--sp-4) 0 var(--sp-6); border-top: 1px solid var(--border); }
.faq details { border-bottom: 1px solid var(--border); }
.faq summary {
  padding: var(--sp-4) var(--sp-6) var(--sp-4) 0;
  cursor: pointer;
  font-weight: 600;
  position: relative;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  position: absolute; right: var(--sp-2); top: 50%; transform: translateY(-50%);
  font-size: var(--fs-lg); color: var(--brand); line-height: 1;
}
.faq details[open] summary::after { content: "−"; }
.faq summary:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--radius-sm); }
.faq-answer { padding: 0 var(--sp-6) var(--sp-4) 0; color: var(--text-muted); max-width: var(--measure); }

.cta-panel {
  margin: var(--sp-7) 0 var(--sp-5);
  padding: var(--sp-6);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--sunken);
}
.cta-panel h2 { margin-top: 0; }
.cta-panel p { max-width: var(--measure); }
.cta-actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin: var(--sp-4) 0 var(--sp-3); }

@media (min-width: 30rem) {
  .stat-row { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 48rem) {
  .reason-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5); }
  .price-grid  { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .lede { font-size: var(--fs-lg); }
}

/* Headings inside migrated bodies are renumbered for the outline by
   ebd_rebase_headings(), so their tag no longer says how big the editor meant
   them to be. Inside an excerpt they are run-in labels, not sections: one
   modest size keeps a renumbered <h2> from shouting over the page title. */
.prose :is(h2, h3, h4, h5, h6) { font-size: var(--fs-md); margin-top: var(--sp-5); }

/* Videos in a post (ebd_embed_videos): one responsive 16:9 frame for all kinds. */
.video-embed {
  position: relative; width: 100%; max-width: 720px; aspect-ratio: 16 / 9;
  margin: var(--sp-5) auto; border-radius: var(--radius); overflow: hidden; background: #0b0b0b;
}
.video-embed iframe, .video-embed video, .video-play, .video-play img {
  position: absolute; inset: 0; width: 100%; height: 100%; border: 0; margin: 0; max-width: none;
}
.video-embed video { object-fit: contain; background: #0b0b0b; }
.video-play { display: block; cursor: pointer; }
.video-play img { object-fit: cover; transition: filter .2s; }
.video-play:hover img { filter: brightness(.85); }
.video-play-btn {
  position: absolute; left: 50%; top: 50%; width: 68px; height: 68px; margin: -34px 0 0 -34px;
  border-radius: 50%; background: rgba(0, 0, 0, .62); box-shadow: 0 2px 12px rgba(0, 0, 0, .35);
  transition: transform .15s, background .15s;
}
.video-play-btn::after {
  content: ""; position: absolute; left: 27px; top: 21px;
  border-style: solid; border-width: 13px 0 13px 22px; border-color: transparent transparent transparent #fff;
}
.video-play:hover .video-play-btn, .video-play:focus-visible .video-play-btn { transform: scale(1.08); background: rgba(0, 0, 0, .78); }
.video-play:focus-visible { outline: 3px solid var(--brand); outline-offset: -3px; }
@media (prefers-reduced-motion: reduce) { .video-play img, .video-play-btn { transition: none; } }

/* ---- deal cards (every deal listing) ------------------------------------ */
/* Richer than the Free eBooks card on purpose: these are the books authors
   pay to feature, so the card carries the genre and the opening line. */
.deal-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);
}
@media (min-width: 48rem) { .deal-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-5); } }
@media (min-width: 64rem) { .deal-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.deal-card {
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  overflow: hidden;
  color: var(--text);
  text-decoration: none;
  box-shadow: var(--shadow-sm);
  transition: transform .16s ease, box-shadow .16s ease;
}
@media (hover: hover) {
  .deal-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }
  .deal-card:hover .deal-card-title { color: var(--brand); }
}
.deal-card:focus-visible { outline: 3px solid var(--brand); outline-offset: 2px; }
.deal-card-stage {
  position: relative;
  aspect-ratio: 1 / 1.05;
  background: var(--sunken);
}
/* The image fills the stage and fits itself inside it (the padding is the
   margin around the book). It used to be a flex item sized by max-height:
   100%, but iOS Safari cannot resolve a percentage height against a box sized
   by aspect-ratio, so it laid the image out at its natural width and the book
   spilled off to the right. Absolute + object-fit is the same everywhere. */
.deal-card-stage img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  box-sizing: border-box; padding: 7% 10%;
  object-fit: contain;
  /* The rendered mockup has a white ground baked in; multiply lets the
     card's tint show through it, leaving just the book and its shadow. */
  mix-blend-mode: multiply;
}
.deal-card-badge {
  position: absolute; top: .7rem; left: .7rem; z-index: 1;
  padding: .2rem .55rem;
  border-radius: var(--radius-pill);
  color: #fff; font-size: var(--fs-xs); font-weight: 750; letter-spacing: .03em;
}
.deal-card-badge.is-free { background: var(--free-fg); }
.deal-card-badge.is-sale { background: var(--price-fg); }
.deal-card-body { display: flex; flex-direction: column; gap: .3rem; padding: var(--sp-3) var(--sp-3) var(--sp-4); flex: 1; }
@media (min-width: 48rem) { .deal-card-body { padding: var(--sp-4) var(--sp-4) var(--sp-4); } }
.deal-card-genre { font-size: .68rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--brand); }
.deal-card-title {
  font-size: var(--fs-md); font-weight: 650; line-height: 1.3; letter-spacing: -.01em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  transition: color .16s ease;
}
.deal-card-author { font-size: var(--fs-sm); color: var(--text-muted); }
.deal-card-blurb {
  display: none;
  font-size: var(--fs-sm); line-height: 1.5; color: #4a4d52;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
@media (min-width: 48rem) { .deal-card-blurb { display: -webkit-box; } }
.deal-card-foot {
  margin-top: auto; padding-top: var(--sp-3);
  display: flex; align-items: flex-end; gap: var(--sp-2);
  border-top: 1px solid var(--sunken);
}
.price-block { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--sp-2); min-width: 0; }
.deal-card-cta { display: none; margin-left: auto; flex: none; font-size: var(--fs-sm); font-weight: 650; color: var(--brand); padding-bottom: 1px; }
@media (min-width: 64rem) { .deal-card-cta { display: inline; } }

/* Giveaways: wide cards, the image shown whole (banners, covers and prize photos alike). */
.giveaway-grid { display: grid; gap: var(--sp-4); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 40rem) { .giveaway-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5); } }
@media (min-width: 64rem) { .giveaway-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.giveaway-card-stage {
  position: relative; display: flex; align-items: center; justify-content: center;
  aspect-ratio: 2 / 1; background: var(--sunken);
}
.giveaway-card-stage img { width: 100%; height: 100%; object-fit: contain; }
.giveaway-prize { font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
.giveaway-prize::before { content: "Prize: "; font-weight: 400; color: var(--text-muted); }
.giveaway-card .giveaway-cta { display: inline; margin-left: 0; }

/* Price row: shared by the cards and the spotlight. */
.price-now { font-size: var(--fs-md); font-weight: 750; font-variant-numeric: tabular-nums; }
.price-now.is-free { color: var(--free-fg); }
.price-now.is-sale { color: var(--price-fg); }
.price-now.is-unknown { font-size: var(--fs-sm); font-weight: 600; color: var(--brand); }
.price-now.is-gone { font-size: var(--fs-sm); font-weight: 600; color: var(--text-muted); }
.price-was { font-size: var(--fs-sm); color: var(--text-muted); text-decoration: line-through; font-variant-numeric: tabular-nums; }
.price-ku { flex-basis: 100%; font-size: var(--fs-xs); color: var(--text-muted); }

/* ---- the Ebook Deals section page ----------------------------------------- */
.deals-head h1 { font-size: var(--fs-3xl); letter-spacing: -.03em; }
.deals-head p { font-size: var(--fs-md); }

.genre-strip { position: relative; display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-5); }
.genre-chip {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .45rem .9rem; min-height: 2.5rem;
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  background: var(--surface); color: var(--text);
  font-size: var(--fs-sm); text-decoration: none; white-space: nowrap;
}
.genre-chip:hover { border-color: #c9c9c3; color: var(--text); }
.genre-chip.is-current { background: var(--text); border-color: var(--text); color: #fff; font-weight: 600; }
/* On phones the strip scrolls sideways rather than wrapping into a wall. */
@media (max-width: 47.99rem) {
  .genre-strip { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-inline: calc(var(--sp-4) * -1); padding-inline: var(--sp-4); }
  .genre-strip::-webkit-scrollbar { display: none; }
  /* The scrolling strip would clip an absolutely placed panel, so on a phone
     the "All genres" button leads the strip and its panel is fixed. */
  .genre-all { order: -1; }
  .genre-panel { position: fixed; left: var(--sp-3); right: var(--sp-3); top: 4.5rem; max-height: calc(100vh - 6rem); }
}
.genre-all { position: static; }
.genre-more { font-weight: 600; cursor: pointer; list-style: none; border-color: #c9c9c3; }
.genre-more::-webkit-details-marker { display: none; }
@media (min-width: 48rem) { .genre-all { margin-left: auto; } }
.genre-all[open] .genre-more { background: var(--text); color: #fff; border-color: var(--text); }
.genre-all[open] .genre-more svg { transform: rotate(180deg); }
.genre-panel {
  position: absolute; left: 0; right: 0; top: calc(100% + var(--sp-2)); z-index: 15;
  max-height: min(70vh, 34rem); overflow-y: auto;
  padding: var(--sp-5);
  background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
  box-shadow: var(--shadow-md);
}
.genre-panel-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-4); margin-bottom: var(--sp-4); }
.genre-panel-head label { font-weight: 650; }
.genre-panel-head input {
  width: min(20rem, 100%); padding: .55rem .75rem;
  border: 1px solid #d6d6d1; border-radius: 9px; font: inherit; font-size: max(16px, var(--fs-sm));
}
.genre-panel-head input:focus-visible { outline: none; border-color: var(--brand); box-shadow: var(--ring); }
.genre-panel-head .muted { margin-left: auto; }
.genre-az {
  list-style: none; margin: 0; padding: 0;
  columns: 2 12rem; column-gap: var(--sp-6);
}
@media (min-width: 64rem) { .genre-az { columns: 4; } }
.genre-az li { break-inside: avoid; }
.genre-az a {
  display: flex; justify-content: space-between; gap: var(--sp-3);
  padding: .4rem 0; border-bottom: 1px solid var(--sunken);
  color: var(--text); text-decoration: none; font-size: var(--fs-sm);
}
.genre-az a:hover { color: var(--brand); }
.genre-az a[aria-current="page"] { font-weight: 700; color: var(--brand); }
.genre-n { color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* The spotlight: the Premium feature currently running. */
.spotlight {
  display: grid;
  background: var(--surface); border: 1px solid var(--border); border-radius: 18px;
  overflow: hidden; box-shadow: var(--shadow-md);
  margin-bottom: var(--sp-7);
}
@media (min-width: 64rem) { .spotlight { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); } }
.spotlight-art { display: block; background: var(--sunken); }
.spotlight-art img { width: 100%; height: 100%; aspect-ratio: 2 / 1; object-fit: cover; }
.spotlight-price .price-block { gap: 0 var(--sp-2); }
.spotlight-body { display: flex; flex-direction: column; gap: var(--sp-2); padding: var(--sp-5); }
@media (min-width: 64rem) { .spotlight-body { padding: var(--sp-6) var(--sp-6); } }
.spotlight-kicker { display: flex; align-items: center; gap: var(--sp-2); margin: 0; font-size: var(--fs-sm); color: var(--text-muted); }
.spotlight-tag {
  padding: .2rem .55rem; border-radius: 6px;
  background: var(--brand); color: #fff;
  font-size: .7rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
}
.spotlight h2 { margin: var(--sp-1) 0 0; font-size: var(--fs-2xl); letter-spacing: -.025em; line-height: 1.1; }
.spotlight h2 a { color: inherit; text-decoration: none; }
.spotlight h2 a:hover { color: var(--brand); }
.spotlight-author { margin: 0; color: var(--text-muted); }
.spotlight-blurb {
  margin: var(--sp-2) 0 0; line-height: 1.55; color: #3a3d42;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
}
.spotlight-buy { margin-top: auto; padding-top: var(--sp-4); display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
.spotlight-price { display: flex; flex-wrap: wrap; align-items: baseline; gap: .15rem var(--sp-2); margin-right: auto; }
.spotlight-price .price-now { font-size: var(--fs-xl); }

.deals-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-4); }
.deals-bar h2 { margin: 0; font-size: var(--fs-xl); letter-spacing: -.02em; }
.deals-filter { display: inline-flex; margin-left: auto; padding: 3px; gap: 3px; background: var(--sunken); border-radius: 10px; }
.deals-filter a { padding: .4rem .8rem; border-radius: 8px; font-size: var(--fs-sm); font-weight: 600; color: var(--text-muted); text-decoration: none; white-space: nowrap; }
.deals-filter a:hover { color: var(--text); }
.deals-filter a[aria-current="page"] { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }

.genre-foot { margin-top: var(--sp-7); padding: var(--sp-5); background: var(--surface); border: 1px solid var(--border); border-radius: 16px; }
.genre-foot h2 { font-size: var(--fs-lg); margin-bottom: var(--sp-4); }

/* On a phone the spotlight's title and art already open the post. */
@media (max-width: 29.99rem) { .spotlight-buy .btn-secondary { display: none; } }

/* ---- social accounts and share buttons ----------------------------------- */
/* Each network brings its own colour (--net); icons are drawn in currentColor. */
.social-facebook  { --net: #0866ff; }
.social-instagram { --net: #e1306c; }
.social-x         { --net: #000000; }
.social-pinterest { --net: #bd081c; }
.social-youtube   { --net: #ff0000; }
.social-tiktok    { --net: #000000; }
.social-threads   { --net: #000000; }
.social-bluesky   { --net: #0285ff; }
.social-goodreads { --net: #5a3d2b; }
.social-website   { --net: var(--brand); }
.social-icon { flex: none; display: block; }

/* Footer: icon pills. */
.social-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); list-style: none; margin: 0; padding: 0; }
.site-footer .social-btn {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .45rem .8rem .45rem .6rem; min-height: 2.5rem;
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  background: var(--surface); color: var(--text);
  font-size: var(--fs-sm); font-weight: 550; text-decoration: none;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.site-footer .social-btn .social-icon { color: var(--net); transition: color .15s ease; }
.site-footer .social-btn:hover, .site-footer .social-btn:focus-visible {
  background: var(--net); border-color: var(--net); color: #fff;
}
.site-footer .social-btn:hover .social-icon, .site-footer .social-btn:focus-visible .social-icon { color: #fff; }

/* Home sidebar: a list with brand tiles. */
.follow-list { list-style: none; margin: var(--sp-3) 0 0; padding: 0; display: grid; gap: var(--sp-2); }
.follow-item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: .55rem .65rem; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text); text-decoration: none;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.follow-item:hover { border-color: var(--net); box-shadow: 0 4px 12px -6px var(--net); transform: translateY(-1px); color: var(--text); }
.follow-icon {
  display: grid; place-items: center; flex: none;
  width: 2.25rem; height: 2.25rem; border-radius: 10px;
  background: var(--net); color: #fff;
}
.social-instagram .follow-icon { background: radial-gradient(circle at 30% 107%, #fdf497 0%, #fd5949 45%, #d6249f 60%, #285aeb 90%); }
.follow-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.follow-text strong { font-size: var(--fs-sm); }
.follow-text span { font-size: var(--fs-xs); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.follow-arrow { margin-left: auto; color: var(--text-muted); flex: none; }
.follow-item:hover .follow-arrow { color: var(--net); }

/* Share buttons on posts and pages. */
.share-btn {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .4rem .75rem .4rem .55rem; min-height: 2.5rem;
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  background: var(--surface); color: var(--text);
  font: inherit; font-size: var(--fs-sm); font-weight: 550; text-decoration: none; cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.share-btn .social-icon { color: var(--net, var(--text-muted)); }
.share-btn:hover, .share-btn:focus-visible { background: var(--net, var(--text)); border-color: var(--net, var(--text)); color: #fff; }
.share-btn:hover .social-icon, .share-btn:focus-visible .social-icon { color: #fff; }
.share-copy.is-done { background: var(--free-bg); border-color: #bfe3cb; color: var(--free-fg); }
.share-copy.is-done .social-icon { color: var(--free-fg); }
@media (max-width: 29.99rem) { .share-btn span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); } .share-btn { padding: .5rem; } }

/* ---- "Feature your book" calls to action (includes/feature_cta.php) ------ */
/* Each section sells the feature that puts a book in it: a line under the
   heading, a banner after the list, a smaller box at the foot of a post. */
.feature-lead { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); font-weight: 650; }
.feature-lead a { color: var(--brand); text-decoration: none; }
.feature-lead a:hover { text-decoration: underline; }

.feature-cta {
  --cta: var(--brand); --cta-bg: #eef3fb; --cta-line: #d5e0f3;
  display: grid; gap: var(--sp-4); align-items: center;
  margin: var(--sp-7) 0 var(--sp-6);
  padding: var(--sp-5);
  background: var(--cta-bg);
  border: 1px solid var(--cta-line);
  border-radius: var(--radius-lg);
}
.feature-cta-free { --cta: var(--free-fg); --cta-bg: var(--free-bg); --cta-line: #c9e8d3; }
.feature-cta-giveaway { --cta: var(--warn-fg); --cta-bg: var(--warn-bg); --cta-line: var(--warn-line); }
@media (min-width: 48rem) {
  .feature-cta { grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-6); padding: var(--sp-6) var(--sp-6); }
}
.feature-cta-kicker { margin: 0 0 var(--sp-1); font-size: .7rem; font-weight: 750; letter-spacing: .09em; text-transform: uppercase; color: var(--cta); }
.feature-cta-title { margin: 0 0 var(--sp-2); font-size: var(--fs-xl); font-weight: 700; line-height: 1.2; letter-spacing: -.015em; color: var(--text); }
.feature-cta-body { margin: 0; max-width: 60ch; color: #3f4247; line-height: 1.55; }
.feature-cta-actions { display: grid; gap: var(--sp-2); justify-items: start; }
@media (min-width: 48rem) { .feature-cta-actions { justify-items: center; text-align: center; } }
.feature-cta .btn { background: var(--cta); border-color: var(--cta); padding-inline: var(--sp-5); }
.feature-cta .btn:hover { filter: brightness(.92); }
.feature-cta-meta { font-size: var(--fs-sm); color: var(--text-muted); }
.feature-cta-meta strong { color: var(--text); }
.feature-cta-meta a { color: inherit; }
@media (max-width: 29.99rem) { .feature-cta .btn { width: 100%; text-align: center; } .feature-cta-actions { justify-items: stretch; } }

/* At the foot of a post: tighter, one column, under the share row. */
.feature-cta.is-compact { margin: var(--sp-6) 0 0; padding: var(--sp-4) var(--sp-5); grid-template-columns: minmax(0, 1fr); gap: var(--sp-3); }
.feature-cta.is-compact .feature-cta-title { font-size: var(--fs-md); margin-bottom: var(--sp-1); }
.feature-cta.is-compact .feature-cta-body { font-size: var(--fs-sm); }
.feature-cta.is-compact .feature-cta-actions { justify-items: start; text-align: left; grid-auto-flow: column; align-items: center; gap: var(--sp-3); justify-content: start; }
@media (max-width: 29.99rem) { .feature-cta.is-compact .feature-cta-actions { grid-auto-flow: row; } }

