/* ===== HERO ===== */

.hero {
  padding-block: var(--space-section-y);
  text-align: center;
  background-color: #E7E7E7;
}

.hero__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-lg);
}

.hero__title {
  /* Wider than --content-narrow-width so the headline breaks onto
     two lines instead of three at desktop widths */
  max-width: 1200px;
}

.hero__content {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-lg);
  align-items: center;
  width: 100%;
}

@media (min-width: 1024px) {
  .hero__content {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2xl);
  }

  /* Copy left, video right (video is first in markup for mobile order) */
  .hero__copy { order: -1; text-align: left; }
}

.hero__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

@media (max-width: 1023px) {
  .hero__copy { align-items: center; }
}

.hero__subtitle {
  max-width: var(--content-narrow-width);
  font-size: var(--font-size-body);
  color: var(--color-text-secondary);
  line-height: var(--line-height-relaxed);
  margin-top: var(--space-lg);
  margin-bottom: var(--space-xl);
}

.hero__video {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background-color: var(--color-bg-alt);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-top: var(--space-md);
  cursor: pointer;
  border: none;
  padding: 0;
}

.hero__video-poster {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.hero__video-iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

.hero__play-button {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hero__play-button::before {
  content: "";
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background-color: var(--color-bg);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.25);
}

.hero__play-button::after {
  content: "";
  position: absolute;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 14px 0 14px 22px;
  border-color: transparent transparent transparent var(--color-text-primary);
  transform: translateX(3px);
}

.hero__cta {
  margin-top: var(--space-md);
}

/* ===== AS SEEN ON ===== */

.as-seen-on {
  padding-block: var(--space-2xl);
  background-color: var(--color-bg);
}

.as-seen-on__label {
  display: block;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  font-size: var(--font-size-h4);
  font-weight: var(--font-weight-bold);
  color: var(--color-blue-primary);
  margin-bottom: var(--space-xl);
}

/* ===== BONUSES ===== */

.bonuses {
  padding-block: var(--space-section-y);
  background-color: var(--color-gray-2);
}

#bonuses-pre-form .section__eyebrow {
  font-size: var(--font-size-hero);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
  color: var(--color-blue-primary);
  margin-bottom: calc(var(--space-3xl) + var(--space-xl));
  text-transform: none;
  letter-spacing: -0.02em;
}

.bonuses__cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-lg);
  margin-top: var(--space-2xl);
  margin-bottom: var(--space-2xl);
}

@media (min-width: 768px) {
  .bonuses__cards { grid-template-columns: 1fr 1fr; }

  /* The lead bonus spans the row and the rest pair up beneath it. Only from three
     cards up: with two, a full-width lead would strand the second one. The count
     comes from Butter and changes per site, so all of this is driven off card
     position rather than a class. */
  .bonuses__cards > .card:first-child:nth-last-child(n+3) {
    grid-column: 1 / -1;
  }

  /* A card left alone on the last row is centred instead of hanging in the left
     column with a hole beside it. Given the full-width lead that means an even
     total (4, 6, …); the :nth-child(n+4) keeps a plain two-card grid — which
     fills its single row — out of it. A lone bonus gets the same treatment. */
  .bonuses__cards > .card:last-child:nth-child(even):nth-child(n+4),
  .bonuses__cards > .card:only-child {
    grid-column: 1 / -1;
    justify-self: center;
    width: calc(50% - var(--space-lg) / 2);
  }
}

.bonuses__card-title {
  font-size: calc(1.75rem * var(--font-scale));
  margin-bottom: var(--space-xl);
}

.bonuses__card-body {
  font-size: calc(1.375rem * var(--font-scale));
  color: var(--color-text-secondary);
  /* Last thing in the card, and the card's padding is the space below it. The
     rich-text default carries a bottom margin because most bodies have something
     after them; here it would just deepen the card. */
  margin-bottom: 0;
}

/* A card's body is one WYSIWYG field, so its list arrives as a bare <ul> with no
   class, and base.css strips list markers from every <ul>. Without these the
   items rendered as unmarked indented text — the arrow and the breathing room
   between items both came from .bonuses__card-list, which now only serves the
   hand-written home page below.

   flex + gap rather than a margin on each item, exactly as that class does, so
   there is no trailing space to undo after the last one. The section block is
   named on the list rules for the same reason it is under ABOUT THE BOOK: the
   .library-rich-text defaults load later and would otherwise win on source
   order. */
.bonuses .bonuses__card-body ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  margin: var(--space-lg) 0 0;
  padding-left: 0;
}

/* Arrow bullets are for unordered lists only; an <ol> keeps its numbers and the
   generic rich-text indent. */
.bonuses .bonuses__card-body ul > li {
  position: relative;
  margin: 0;
  padding-left: var(--space-xl);
}

.bonuses__card-body ul > li::before {
  content: "→";
  position: absolute;
  left: 0;
  color: var(--color-blue-primary);
  font-weight: var(--font-weight-bold);
}

.bonuses__card-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  font-size: calc(1.375rem * var(--font-scale));
}

.bonuses__card-list li {
  position: relative;
  padding-left: var(--space-xl);
  color: var(--color-text-secondary);
  line-height: var(--line-height-relaxed);
}

.bonuses__card-list li::before {
  content: "→";
  position: absolute;
  left: 0;
  color: var(--color-blue-primary);
  font-weight: var(--font-weight-bold);
}

.bonuses__form-heading {
  text-align: center;
  margin-top: var(--space-3xl);
  margin-bottom: var(--space-2xl);
}

.bonus-form-region__layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-xl);
  align-items: center;
}

@media (min-width: 768px) {
  .bonus-form-region__layout {
    grid-template-columns: 1fr 1fr;
    gap: 0;
  }
}

.bonus-form-region__image {
  display: flex;
  justify-content: center;
  margin-top: var(--space-xl);
}

.bonus-form-region__image img {
  width: 60%;
  max-width: 480px;
  height: auto;
  transform: rotate(-6deg);
  //box-shadow: 0 18px 40px rgba(0, 0, 0, 0.18);
  border-radius: var(--radius-lg);
}

@media (min-width: 768px) {
  .bonus-form-region__image img {
    width: 100%;
  }
}

.bonus-form-region__form {
  position: relative;
  z-index: 2;
  background-color: rgba(238, 238, 238, 0.5);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-radius: var(--radius-xl);
  padding: 40px;
}

@media (min-width: 768px) {
  .bonus-form-region__form {
    margin-left: calc(-1 * var(--space-2xl));
  }
}

.bonuses__success {
  //max-width: 640px;
  margin: 0 auto;
  //background-color: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  //padding: var(--space-2xl);
  text-align: center;
  scroll-margin-top: calc(var(--header-height) + var(--space-xl));
}

.bonuses__success-title {
  margin-bottom: var(--space-2xl);
  margin-top: var(--space-md);
}

.bonuses__success-subtitle {
  color: var(--color-text-secondary);
  margin-bottom: var(--space-3xl);
}

.bonuses__success-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
  text-align: left;
}

/* One card for both shapes (see _success.html.erb): a white header band over a
   tinted body. The shell owns the radius and clips to it, so the header and body
   need no corner radii of their own. */
.bonuses__success-row,
.bonuses__success-video {
  display: flex;
  flex-direction: column;
  background-color: var(--color-bg);
  //border: 1px solid var(--color-blue-primary);
  border-radius: var(--radius-xl);
  overflow: hidden;
}

.bonuses__success-card__header {
  text-align: center;
  background-color: var(--color-bg);
  padding: var(--space-xl);
}

.bonuses__success-card__body {
  /* One width for the cover image and the CTA beneath it, so the two read as a
     single block rather than two differently-sized things. Declared here because
     both children resolve it, and capped at 100% for a narrow phone. */
  --bonus-cta-width: 17rem;

  /* Grows to the bottom of the card: the columns stretch to the tallest one, and
     without this the tint would stop where the content does and leave the shell's
     white showing. A flex column so the CTA can be pinned to the foot of it. */
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--space-xl);
  background-color: var(--color-gray-1);
}

.bonuses__success-card__header span {
  color: var(--color-text-secondary);
}

.bonuses__success-row span,
.bonuses__success-row strong {
  //color: #ffffff;
}

.bonuses__success-row-body {
  color: var(--color-text-secondary);
  //max-width: 560px;
}

/* A step below page body size for both card shapes: at column width, full-size
   body copy wraps every few words. Relative to the body token so it keeps
   tracking --font-scale. */
.bonuses__success-row-body,
.bonuses__success-video-copy {
  font-size: calc(var(--font-size-body) * 0.85);
}

/* Two selectors per rule throughout: `.bonuses__success-row-list` is the class the
   legacy hand-written success panel used, and `.bonuses__success-row-body ul` is
   what Butter actually emits — its WYSIWYG writes a bare <ul> with no class, so
   the row's bullets can only be reached as a descendant. Same lesson as
   `.bonuses__card-body ul` on the pre-form cards.

   The two-class selector also outranks the generic `.library-rich-text ul`
   defaults at the foot of this file (two classes beats one class + one element),
   so it wins regardless of source order. */
.bonuses__success-row-list,
.bonuses__success-row-body ul {
  list-style: none;
  padding: 0;
  margin: 0 0 0 var(--space-xl);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  //max-width: 560px;
  text-align: left;
}

.bonuses__success-row-list li,
.bonuses__success-row-body ul li {
  position: relative;
  padding-left: var(--space-2xl);
  color: var(--color-text-secondary);
  margin-bottom: 0;
}

.bonuses__success-row-list li::before,
.bonuses__success-row-body ul li::before {
  content: "→";
  position: absolute;
  left: 0;
  color: var(--color-blue-secondary);
}


/* The delivered file's cover, above the row's button and the same width as it.
   Sized rather than fluid: the uploads are portrait covers a thousand pixels tall,
   and at full column width one would dominate the card. */
.bonuses__success-row-image {
  display: block;
  width: min(var(--bonus-cta-width), 100%);
  height: auto;
  /* Both vertical margins are its own: the CTA below it is pinned with
     margin-top: auto, which collapses to nothing on a card whose content already
     fills the column — the cover would then sit flush against the button. */
  margin: var(--space-lg) auto;
  border-radius: var(--radius-lg);
}

/* Wraps the cover when the row delivers a file, so the picture is a second way to
   get it. A block, so the image's own centring margins resolve against the card
   body rather than an inline box. */
.bonuses__success-row-image-link {
  display: block;
}

.bonuses__success-video {
  margin-top: var(--space-md);
}

.bonuses__success-video-copy {
  text-align: center;
  padding: 10px 40px 50px 40px;
}

.bonuses__success-video h3 {
  margin-bottom: var(--space-sm);
}

.bonuses__success-video-wrapper {
  /* Pinned to the foot of the card, matching the CTA on the link rows: free space
     collects above the player instead of below it, so the three cards' bottom
     elements line up across the row. */
  margin-top: auto;
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.bonuses__success-video-wrapper iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: var(--radius-lg);
}

/* Desktop: the delivered bonuses sit side by side instead of stacking, with the
   lead bonus spanning the row above the rest — the same three rules as the
   pre-form .bonuses__cards grid, and for the same reasons: the number of rows
   comes from a Butter repeater and differs per site, so the layout is driven off
   card position rather than a count. Two columns rather than auto-fit tracks
   because a full-width lead over auto-fit tracks leaves the pair beneath it
   sitting in two of three columns with a hole beside them.

   1024px rather than the 768px used elsewhere in this file: these cards carry a
   cover image or a video player under several paragraphs, so a half-width column
   on a tablet runs absurdly tall. Below this they stay stacked, full width. */
@media (min-width: 1024px) {
  .bonuses__success-list {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }

  /* Only from three bonuses up: with two, a full-width lead would strand the
     second one on its own row. */
  .bonuses__success-list > *:first-child:nth-last-child(n+3) {
    grid-column: 1 / -1;
  }

  /* A bonus left alone on the last row is centred rather than hanging in the left
     column. Given the full-width lead that means an even total (4, 6, …); the
     :nth-child(n+4) keeps a plain two-bonus grid — which fills its single row —
     out of it. */
  .bonuses__success-list > *:last-child:nth-child(even):nth-child(n+4),
  .bonuses__success-list > *:only-child {
    grid-column: 1 / -1;
    justify-self: center;
    width: calc(50% - var(--space-md) / 2);
  }

  /* Stacked, this margin separated the video card from the row above it; in a
     row of columns it would just drop that column out of alignment. */
  .bonuses__success-video {
    margin-top: 0;
  }

  /* Side padding tuned for a full-width card eats a third-width column. */
  .bonuses__success-video-copy {
    padding: var(--space-sm) var(--space-md) var(--space-lg);
  }
}

.bonuses__success-note {
  margin-top: var(--space-xl);
  font-size: var(--font-size-xs);
  color: var(--color-text-secondary);
}

/* The video card's copy is a WYSIWYG body, so it arrives as <p> rather than the
   bare <span> the hand-written panel used — `.bonuses__success-video span` above
   cannot reach it. Restate the muted colour on the container instead. */
.bonuses__success-video-copy {
  color: var(--color-text-secondary);
}

/* Separates the raw success_custom_code escape hatch from the rows above it. The
   embed inside is arbitrary, so this sets spacing only and imposes no layout. */
.bonuses__success-custom {
  margin-top: var(--space-lg);
}

/* Both shapes put their CTA in the card body, a plain block where an inline-flex
   button would sit left against `.bonuses__success-list`'s left-aligned text.
   Centre it under the copy. (The rows used to centre theirs for free, as a
   centre-aligned flex column; the shared card shell no longer aligns its children
   that way.) */
.bonuses__success-card__body .button {
  display: flex;
  width: min(var(--bonus-cta-width), 100%);
  /* .button is nowrap by default, which would overflow this fixed width; a label
     longer than the cover is wide wraps inside the button instead. */
  white-space: normal;
  margin-inline: auto;
  /* Pinned to the foot of the body, so the CTAs line up across a row of cards
     whose copy runs to different lengths instead of each floating under its own
     last paragraph. The min-height keeps a gap from the copy on a card whose
     content fills the whole column and leaves no free space to absorb. */
  margin-top: auto;
}

/* ===== ABOUT THE BOOK ===== */

.about-book {
  padding-block: var(--space-section-y);
  background-color: var(--color-blue-primary);
}

.about-book .section__eyebrow {
  color: var(--color-blue-light);
}

.about-book__columns {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2xl);
  margin-top: var(--space-xl);
}

@media (min-width: 1024px) {
  .about-book__columns { grid-template-columns: 1fr 1fr; }
}

.about-book__col-title {
  font-size: calc(1.875rem * var(--font-scale));
  margin-bottom: var(--space-2xl);
  color: #FFFFFF;
}

/* A column's copy is one WYSIWYG field, so it arrives as bare <p>, <ul>, <li>
   and <strong> with no classes — hence descendant selectors on the body rather
   than the old .about-book__list / .about-book__paragraph classes. Typography
   is set once on the container and the nested blocks inherit it via the
   .library-rich-text rules at the foot of this file. The list rules name the
   section block as well: those same rich-text defaults load later and would
   otherwise win the cascade on source order. */
.about-book__body {
  color: var(--color-cool-gray);
  line-height: var(--line-height-relaxed);
  font-size: var(--font-size-body-lg);
}

.about-book__body strong {
  color: #FFFFFF;
}

.about-book__body p + p {
  margin-top: var(--space-md);
}

.about-book .about-book__body ul {
  margin: 0 0 var(--space-lg);
  padding-left: 0;
}

/* Arrow bullets are for unordered lists only; an <ol> keeps its numbers and the
   generic rich-text indent. */
.about-book .about-book__body ul > li {
  position: relative;
  padding-left: var(--space-xl);
  margin-bottom: var(--space-md);
}

.about-book__body ul > li::before {
  content: "→";
  position: absolute;
  left: 0;
  color: var(--color-yellow);
  font-weight: var(--font-weight-bold);
}

@media (max-width: 768px) {
  .about-book__body {
    font-size: var(--font-size-form);
  }
}

/* ===== AUDIOBOOK ===== */

.audiobook {
  padding-block: var(--space-section-y);
}

.audiobook__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-md);
  max-width: var(--content-narrow-width);
  margin-inline: auto;
}

.audiobook__title {
  margin-bottom: var(--space-xs);
}

.audiobook__body {
  color: var(--color-text-secondary);
}

.audiobook__cover {
  width: 200px;
  margin: var(--space-xl) auto 0;
  border-radius: var(--radius-md);
}

.audiobook__player {
  width: 100%;
  max-width: 560px;
  margin-block: var(--space-md);
}

.audiobook__inner .plyr {
  width: 100%;
  margin-top: var(--space-sm);
  margin-bottom: var(--space-lg);
  overflow: visible !important;
  --plyr-color-main: var(--color-blue-primary);
  --plyr-audio-controls-background: var(--color-gray-2);
  --plyr-audio-control-color: var(--color-blue-primary);
  --plyr-audio-control-color-hover: var(--color-blue-secondary);
  --plyr-audio-control-background-hover: transparent;
  --plyr-range-fill-background: var(--color-blue-primary);
  --plyr-range-thumb-background: var(--color-blue-primary);
  --plyr-control-spacing: 14px;
  --plyr-range-track-height: 4px;
  --plyr-range-thumb-height: 14px;
  --plyr-range-thumb-width: 14px;
  border-radius: var(--radius-xl);
  overflow: hidden;
}

/* ===== TESTIMONIALS ===== */

.testimonials {
  padding-block: var(--space-section-y);
  background-color: var(--color-gray-2);
  font-size: calc(1rem * var(--font-scale));
  font-weight: var(--font-weight-medium);
}

/* ===== MEET AUTHORS ===== */

.meet-authors {
  //padding-block: var(--space-section-y);
  text-align: center;
}

/* Here the eyebrow is the kicker *under* the heading (see _author_list), not a
   label above one, so layout.css's bottom margin — which exists to separate an
   eyebrow from the heading below it — would just pad out the hero. The hero's own
   60px padding is the space below. Applies to both places this component runs:
   /the-authors and the home page's authors section. */
.meet-authors .section__eyebrow {
  margin-bottom: 0;
}


.meet-authors__photos {
  display: flex;
  justify-content: center;
  gap: var(--space-lg);
  margin-top: var(--space-xl);
  flex-wrap: wrap;
}

.meet-authors__photo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
}

.meet-authors__image {
  width: 160px;
  height: 160px;
  border-radius: 50%;
  object-fit: cover;
}

.meet-authors__image--dan {
  object-position: 50% 0%;
}

@media (min-width: 768px) {
  .meet-authors__image {
    width: 240px;
    height: 240px;
  }
}

.meet-authors__name {
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-body-lg);
}

.meet-authors__bio {
  max-width: var(--content-narrow-width);
  margin: var(--space-2xl) auto 0;
  text-align: center;
  color: var(--color-text-secondary);
}

.meet-authors__bio p + p {
  margin-top: var(--space-md);
}

/* ===== FINAL CTA ===== */

.final-cta {
  padding-block: var(--space-section-y);
  background-color: var(--color-bg-alt);
  text-align: center;
}

.final-cta__title {
  margin-bottom: var(--space-md);
  color: var(--color-blue-primary);
}

.final-cta__body {
  max-width: var(--content-narrow-width);
  margin: 0 auto var(--space-3xl);
  color: var(--color-text-secondary);
  line-height: var(--line-height-relaxed);
}

.final-cta__retailer-label {
  margin: 0 0 var(--space-xl);
  color: var(--color-text-secondary);
  font-size: var(--font-size-form);
  font-weight: var(--font-weight-regular);
}

.final-cta__buttons {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-md);
}

@media (max-width: 768px) {
  .final-cta__buttons {
    flex-direction: column;
    align-items: stretch;
  }
  .final-cta__buttons .button { width: 100%; }
}

.final-cta__buttons .button {
  /* The label is a caption under a retailer logo, not the button's voice — the
     logo carries the recognition, so the text sits a step below --font-size-small. */
  font-size: var(--font-size-xs);
  line-height: var(--line-height-normal);
  gap: var(--space-sm);
  flex-direction: column;
  color: var(--color-text-secondary); /* was text-muted (#888) — failed AA; text-secondary (#404040) passes */
  background-color: var(--color-bg);
  /* No border: the white fill against the section behind it is what separates
     these, and the hover shadow is what responds to the pointer. An outline on top
     of that read as a box drawn around each logo. */
  border-radius: var(--radius-lg);
  /* --space-2xl side padding left only 104px of content box in a six-up row,
     which is narrower than the widest logos need at their set height; they were
     the ones being squashed. */
  padding: var(--space-lg);
  height: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 0 rgba(0, 0, 0, 0);
  transition: box-shadow var(--transition-normal);
  flex: 1 1 0;
  min-height: 130px;
  white-space: normal;
  text-align: center;
}

.final-cta__buttons .button:hover {
  background-color: var(--color-bg);
  color: var(--color-text-secondary);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}

.final-cta__retailer-logo {
  display: block;
  width: auto;
  /* The per-retailer modifiers below set an explicit height, and the base reset
     caps every img at max-width: 100%. In a button narrower than the logo needs at
     that height, both constraints bind at once and the default object-fit: fill
     stretches the artwork to the resulting box — Barnes & Noble is 11:1, so it was
     rendering at 6.5:1. `contain` scales it down proportionally instead. */
  object-fit: contain;
  filter: none;
  opacity: 1;
  transition: filter var(--transition-fast), opacity var(--transition-fast);
}

.final-cta__buttons .button:hover .final-cta__retailer-logo {
  filter: brightness(0);
  opacity: 0.55;
}

.final-cta__retailer-logo--amazon { 
  height: 30px; 
  //transform: translateY(15px); 
  transform: translateY(6px); 
}
.final-cta__retailer-logo--audible { 
  height: 33px; 
  //transform: translateY(0); 
  transform: translateY(-5px); 
}
.final-cta__retailer-logo--sc-store { 
  height: 75px; 
  //transform: translateY(5px); 
}
.final-cta__retailer-logo--porchlight { 
  height: 55px; 
  //transform: translateY(-7px); 
}
.final-cta__retailer-logo--barnes-noble { 
  height: 16px; 
  //transform: translateY(8px); 
}
.final-cta__retailer-logo--bookshop { 
  height: 25px; 
  //transform: translateY(6px); 
}

/* ===== PODCAST PAGE ===== */

.podcast-page {
  padding-block: var(--space-section-y);
  text-align: center;
  background-color: var(--color-gray-2);
}

.podcast-page__title {
  max-width: var(--content-narrow-width);
  margin: 0 auto var(--space-2xl);
}

.podcast-page__body {
  max-width: var(--content-narrow-width);
  margin: 0 auto var(--space-md);
  color: var(--color-text-secondary);
}

.podcast-page__subscribe-card {
  background-color: #EBF2F7;
}

.podcast-page__subscribe-label {
  //margin-top: var(--space-2xl);
  font-size: var(--font-size-small);
  color: var(--color-text-secondary);
  margin-bottom: var(--space-md);
}

.podcast-page__subscribe-buttons {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2xl);
  margin-bottom: var(--space-xl);
}

.podcast-btn {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  width: 100px;
  text-decoration: none;
  color: var(--color-text-primary);
  font-size: var(--font-size-small);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  transition: opacity var(--transition-fast);
}

.podcast-btn:hover {
  opacity: 0.7;
}

.podcast-btn__icon {
  width: 56px;
  height: 56px;
  object-fit: contain;
}

.podcast-page__note {
  font-size: var(--font-size-small);
  color: var(--color-text-muted);
  font-style: italic;
}

/* ===== MEASUREMENTS PAGE ===== */

.measurements-page {
  padding-block: var(--space-section-y);
  background-color: var(--color-gray-2);
}

.measurements-page__intro {
  max-width: var(--content-narrow-width);
  margin: 0 auto var(--space-2xl);
  text-align: center;
}

.measurements-page__intro-body {
  margin-top: var(--space-md);
  color: var(--color-text-secondary);
  line-height: var(--line-height-relaxed);
}

.measurements-page__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-lg);
  margin-bottom: var(--space-2xl);
}

@media (min-width: 768px) {
  .measurements-page__grid { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 1024px) {
  .measurements-page__grid { grid-template-columns: repeat(4, 1fr); }
}

.measurement-card__stage {
  display: block;
  font-size: var(--font-size-small);
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.1em;
  color: var(--color-blue-muted);
  text-transform: uppercase;
  margin-bottom: var(--space-sm);
}

.measurement-card__name {
  font-size: var(--font-size-h3);
  margin-bottom: var(--space-md);
}

.measurement-card__body {
  color: var(--color-text-secondary);
  line-height: var(--line-height-relaxed);
}

.measurements-page__cta {
  text-align: center;
  margin-top: var(--space-xl);
}

.measurements-page__cta-text {
  margin-bottom: var(--space-lg);
  color: var(--color-text-secondary);
}

/* ===== AUTHORS PAGE ===== */

.authors-page {
  padding-block-start: var(--space-section-y);
  padding-block-start: 0;
  padding-block-end: 0;
  background-color: var(--color-bg);
}

.authors-page__hero {
  text-align: center;
  max-width: var(--content-narrow-width);
  margin: auto;
  padding: 60px 0;
}

.author-section {
  padding-block: var(--space-lg) 0;
  background-color: var(--color-gray-2);
  overflow: hidden;
}

.author-section--reverse {
  background-color: var(--color-cool-gray);
}

.author-section__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
  align-items: center;
}

@media (min-width: 768px) {
  .author-section__inner { grid-template-columns: 1.4fr 1fr; gap: var(--space-2xl); }
  .author-section--reverse .author-section__inner { grid-template-columns: 1fr 1.1fr; }
  .author-section--reverse .author-section__image { order: 2; }
}

.author-section__content {
  padding-block: var(--space-lg);
  text-align: center;
}

@media (min-width: 768px) {
  .author-section__content { padding-block: var(--space-section-y); }
}

.author-section__image {
  align-self: end;
  position: relative;
}

.author-section__image::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, transparent 59%, var(--color-gray-2) 100%);
  pointer-events: none;
}

.author-section--reverse .author-section__image::after {
  background: linear-gradient(to bottom, transparent 55%, var(--color-cool-gray) 100%);
}

@media (min-width: 768px) {
  .author-section__image::after { display: none; }
}

.author-section__image img {
  display: block;
  width: 100%;
  max-width: 100%;
}

.author-section--reverse .author-section__image img {
  width: 88%;
  margin-inline: auto;
}

.author-section__name {
  margin-bottom: var(--space-lg);
  color: var(--color-blue-primary);
  /* Mobile-first, like the rest of this section: 4.5rem is a full-bleed name on a
     390px screen, so the phone size is the base and the desktop size is added at
     the breakpoint. */
  font-size: 3.5rem;
}

@media (min-width: 768px) {
  .author-section__name { font-size: 4.5rem; }
}

.author-section__bio {
  color: var(--color-text-secondary);
  line-height: var(--line-height-relaxed);
  text-align: center;
}

.authors-page__closing-wrap {
  background-color: var(--color-gray-2);
  padding-block: var(--space-3xl);
}

.authors-page__closing {
  text-align: center;
  max-width: var(--content-narrow-width);
  margin: 0 auto;
  font-size: var(--font-size-h3);
  font-weight: var(--font-weight-bold);
  color: var(--color-blue-primary);
  line-height: var(--line-height-relaxed);
}

/* ===== BULK ORDERS PAGE ===== */

.bulk-orders-page {
  padding-block: var(--space-section-y);
  background-color: var(--color-gray-2);
  flex: 1;
}

.bulk-orders-page__hero {
  text-align: center;
  max-width: var(--content-narrow-width);
  margin: 0 auto var(--space-2xl);
}

.bulk-orders-page__body {
  margin-top: var(--space-md);
  color: var(--color-text-secondary);
  line-height: var(--line-height-relaxed);
  text-align: left;
}

.porchlight-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-lg);
  background-color: var(--color-gray-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-xl);
  max-width: 800px;
  margin: var(--space-2xl) auto 0;
  text-align: center;
}

.podcast-page__subscribe-card.porchlight-card {
  background-color: var(--color-bg);
}

.porchlight-card__body {
  flex: 1;
  color: var(--color-text-secondary);
}

/* The partner logo and its caption are one button (two Butter fields, one link),
   stacked by the column flex direction .final-cta__buttons .button already sets.
   The caption is deliberately quieter than the logo it sits under. */
.porchlight-card__cta-label {
  font-size: var(--font-size-xs);
  line-height: var(--line-height-normal);
}

/* Only one button here, so it sizes to its content instead of stretching to the
   full 800px card the way a row of retailer buttons does. */
.porchlight-card .final-cta__buttons .button {
  flex: 0 1 auto;
  min-width: min(240px, 100%);
}

/* The logo comes from Butter, so there is no per-retailer modifier class to
   carry a height the way the hard-coded retailer buttons have. Sized a little
   larger than the 55px --porchlight height of the original bulk-orders card:
   this is the only button in the card, so the logo carries it.
   max-height must be cleared too — the `.final-cta__retailer-logo { max-height:
   40px }` fallback cap further down clamps any height set here, and max-height
   wins over height no matter the specificity. */
.porchlight-card .final-cta__retailer-logo {
  height: 62px;
  max-height: none;
  max-width: 100%;
  object-fit: contain;
}

@media (max-width: 768px) {
  .porchlight-card .final-cta__retailer-logo { height: 50px; }
}

.button__retailer-logo {
  height: 44px;
  width: auto;
  filter: brightness(0) saturate(100%) invert(18%) sepia(23%) saturate(766%) hue-rotate(163deg) brightness(94%) contrast(93%);
  transition: filter var(--transition-fast);
}

.button:hover .button__retailer-logo {
  filter: brightness(0) invert(1);
}

/* ===========================================================================
   Library component sections. Layout for the Butter-backed components that had
   no direct counterpart in the original single-tenant site.
   =========================================================================== */

/* Interior-page hero (library_hero) */
.page-hero { padding: var(--space-section-y) 0 var(--space-2xl); }
.page-hero__inner { text-align: center; }
.page-hero__body {
  max-width: var(--content-narrow-width);
  margin: 0 auto var(--space-xl);
  color: var(--color-text-secondary);
  /* Long-form prose. Two of the three hand-written intros this replaced —
     .bulk-orders-page__body and .measurements-page__intro-body — set relaxed
     leading and lost it in the port; only .podcast-page__body did not. */
  line-height: var(--line-height-relaxed);
}
.page-hero__image { max-width: 100%; height: auto; margin-top: var(--space-xl); }

/* Generic rich text (library_text_block) */
.text-block { padding: var(--space-section-y) 0; }
.text-block--center { text-align: center; }
.text-block__body {
  color: var(--color-text-secondary);
  /* As .page-hero__body: every hand-written prose block set relaxed leading. */
  line-height: var(--line-height-relaxed);
}

/* Retailer strip as a page component (library_retailer_bar) */
.retailer-bar { padding: var(--space-lg) 0; border-block: 1px solid var(--color-border); }
.retailer-bar__intro {
  display: block;
  margin-bottom: var(--space-sm);
  font-size: var(--font-size-small);
  text-align: center;
  color: var(--color-text-secondary);
}
.retailer-bar__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-lg);
  align-items: center;
  justify-content: center;
}
.retailer-bar__logo { max-height: 28px; width: auto; }
.retailer-bar--grid .retailer-bar__list { gap: var(--space-xl); }

/* Framework list (library_framework_list) */
.framework-list { padding: var(--space-section-y) 0; }
.framework-list__intro { text-align: center; margin-bottom: var(--space-2xl); }
.framework-list__intro-body {
  max-width: var(--content-narrow-width);
  margin: 0 auto;
  color: var(--color-text-secondary);
}
.framework-list__grid { display: grid; gap: var(--space-lg); }
.framework-list__grid--2 { grid-template-columns: 1fr; }
.framework-list__grid--3 { grid-template-columns: 1fr; }
.framework-list__grid--4 { grid-template-columns: 1fr; }
.framework-list__icon { max-height: 48px; width: auto; margin-bottom: var(--space-md); }
.framework-list__label {
  display: block;
  margin-bottom: var(--space-xs);
  font-size: var(--font-size-small);
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-yellow);
}
.framework-list__name { margin-bottom: var(--space-sm); }
.framework-list__body { color: var(--color-text-secondary); }
.framework-list__cta { margin-top: var(--space-2xl); text-align: center; }
.framework-list__cta-text { margin-bottom: var(--space-md); }

@media (min-width: 768px) {
  .framework-list__grid--2 { grid-template-columns: repeat(2, 1fr); }
  .framework-list__grid--3 { grid-template-columns: repeat(3, 1fr); }
  .framework-list__grid--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  .framework-list__grid--4 { grid-template-columns: repeat(4, 1fr); }
}

/* Standalone button row (library_buttons) */
.button-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  padding: var(--space-xl) 0;
}
.button-row--left   { justify-content: flex-start; }
.button-row--center { justify-content: center; }
.button-row--right  { justify-content: flex-end; }

/* Logo marquee items (library_logo_marquee) */
.marquee__item { display: inline-flex; align-items: center; padding-inline: var(--space-xl); }
.marquee__logo { max-height: 40px; width: auto; }
.marquee--slow   .marquee__track { animation-duration: 60s; }
.marquee--medium .marquee__track { animation-duration: 40s; }
.marquee--fast   .marquee__track { animation-duration: 20s; }

/* Author role line (library_author_list) */
.author-section__title {
  margin-bottom: var(--space-sm);
  font-size: var(--font-size-small);
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* Audiobook player (library_audiobook) */
.audiobook__player { width: 100%; margin-block: var(--space-lg); }

/* Hero with no video collapses to a single column */
.hero__content--no-video { grid-template-columns: 1fr; }

/* Dark call to action (library_call_to_action theme=dark) */
.final-cta--dark {
  background: var(--color-blue-primary);
  color: var(--color-cta-text);
}
.final-cta--dark .final-cta__title,
.final-cta--dark .final-cta__body { color: var(--color-cta-text); }

/* ===========================================================================
   Bonuses section heading
   main styles this text via `#bonuses-pre-form .section__eyebrow` on an <h1>.
   library_bonus_form renders it as a semantic h2.section__title instead, so the
   same treatment is scoped to the component. Values kept in step with that rule.
   =========================================================================== */
.bonuses .section__title {
  font-size: var(--font-size-hero);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
  letter-spacing: -0.02em;
  color: var(--color-blue-primary);
  margin-bottom: calc(var(--space-3xl) + var(--space-xl));
}

/* Retailer logos are sized by per-retailer modifier classes (--amazon,
   --sc-store, --barnes-noble, …). .final-cta__retailer-logo has no base height, so
   a logo whose Logo Key matches no rule rendered at intrinsic SVG size — which on
   these files is several hundred pixels tall. This caps the fallback: a
   misconfigured key now looks slightly wrong rather than breaking the layout. */
.final-cta__retailer-logo { max-height: 40px; }
.retailer-bar__logo { max-height: 32px; }


/* ===========================================================================
   WYSIWYG containers (.library-rich-text)

   The live site puts typography classes directly on the <p>, e.g.
   `<p class="testimonials-grid__quote">`, so the class wins over the base `p`
   rule. Butter returns a WYSIWYG field as its own markup, so a component has to
   wrap it: `<div class="testimonials-grid__quote"><p>…</p></div>`. The inner <p>
   then matches base.css `p { font-size: var(--font-size-body-lg) }` — 1.5rem —
   and overrides the container. On the testimonial quote that meant 24px instead
   of 16px.

   One rule, applied to every WYSIWYG container, rather than a per-container fix:
   nested block elements take the container's typography.
   =========================================================================== */
.library-rich-text > p,
.library-rich-text > ul,
.library-rich-text > ol,
.library-rich-text > blockquote {
  font-size: inherit;
  line-height: inherit;
}

.library-rich-text > :first-child { margin-top: 0; }
.library-rich-text > :last-child { margin-bottom: 0; }

/* Lists arrive from Butter as bare <ul>/<ol> with no class. */
.library-rich-text ul,
.library-rich-text ol {
  margin: var(--space-md) 0;
  padding-left: var(--space-lg);
}

.library-rich-text li { margin-bottom: var(--space-xs); }
.library-rich-text li:last-child { margin-bottom: 0; }

/* ===========================================================================
   Section bands. The vocabulary for the Butter `css_class` fields, applied by
   pages/show.html.erb — to each component's wrapper div, and to the single
   <section> the page type's own css_class wraps every component in.

   Together these are what a page composed of components uses to reproduce the
   banding the hand-written pages got from their root <section> — the grey
   behind /podcast and /bulk-book-orders, for example.

   Composable: `css_class` takes a space-separated list, e.g.
   "section--muted section--fill".
   =========================================================================== */

/* The grey band. Matches the legacy .podcast-page / .measurements-page /
   .bulk-orders-page background. */
.section--muted { background-color: var(--color-gray-2); }

/* The lighter band, matching the header and footer surface. */
.section--alt { background-color: var(--color-bg-alt); }

/* Vertical padding, for components that carry none of their own.
   Most section-rooted components already pad themselves — .text-block,
   .page-hero, .framework-list — and adding this to those would double it.
   The components that need it are the ones rooting at a bare .container:
   library_buttons, library_partner_card, library_podcast_subscribe.

   The one-sided pair is for a page band whose ends are padded unequally by
   what is inside it. A page opening with library_hero already has its top
   padding from .page-hero and needs only --pad-end; using --pad there would
   stack two full --space-section-y at the top. */
.section--pad       { padding-block: var(--space-section-y); }
.section--pad-start { padding-block-start: var(--space-section-y); }
.section--pad-end   { padding-block-end: var(--space-section-y); }

/* Stretch a band to the footer. <main> is a column flex container
   (layout.css), so this makes a short page fill the viewport instead of
   leaving white below the band. This is what .bulk-orders-page used flex: 1
   for, and what .podcast-page was missing.

   Goes on whichever element is the direct child of <main>: the last component
   wrapper on an unwrapped page, or the page <section> when the page type's
   css_class is set. Inside a page <section> it has no effect, since that
   section is not itself a flex container. */
.section--fill { flex: 1; }


/* ===========================================================================
   Prose alignment, as a context.

   The hand-written pages tuned their copy through per-page BEM blocks, so each
   page's body carried its own rules: .bulk-orders-page__body set
   text-align: left inside a .bulk-orders-page__hero that was centred, while
   .podcast-page__body and .measurements-page__intro-body stayed centred. The
   components collapsed all three into one .page-hero__body, which can only
   have one alignment — so the bulk-orders copy came back centred.

   Those legacy selectors cannot be revived by naming a page. They are flat BEM
   (`.bulk-orders-page__body`), matching only an element that literally carries
   that class, so a page-level css_class of "bulk-orders-page" reaches nothing:
   the element beneath it is .page-hero__body. A page class only works as a
   CONTEXT, which means a descendant selector — the form used here.

   The hook is .library-rich-text, which every WYSIWYG body container already
   carries and a test in ComponentsTest enforces. So one pair of rules covers
   every component, at any depth, and works identically whether the class is
   typed into a component's css_class or the page's.

   Only the body copy moves; headings keep the alignment their component gives
   them. That is exactly the legacy shape — centred hero, left-aligned prose. */
.section--body-left  .library-rich-text { text-align: left; }
.section--body-right .library-rich-text { text-align: right; }

/* The inverse, for a component whose own rules align left. */
.section--body-center .library-rich-text { text-align: center; }

/* "At any depth" reaches further than intended: a self-contained card that
   happens to sit in the section is not the section's prose, and its own centring
   is part of the card rather than a default waiting to be overridden. On
   /bulk-book-orders the page carries section--body-left for its two intro
   paragraphs, and that was pulling the Porchlight card's single centred line
   flush left under a centred logo.

   Two classes each, the same as the rules above, so these have to stay below
   them. Named per component because only the component knows its body is not
   the section's prose. */
.section--body-left  .porchlight-card__body,
.section--body-right .porchlight-card__body,
.section--body-left  .author-section__bio,
.section--body-right .author-section__bio {
  text-align: center;
}
