/* ============================================
   BUSINESS FOUNDERS: Founder Series compartments
   Full-screen themed sections, one per book, with
   scroll-snap. Palette arrives as CSS variables on
   each .comp from js/books-config.js.

   Choreography classes (set by js/books.js):
   .shown  : entrance: book sweeps in from the right
   .active: centre-stage: signature effect plays
   --scrollp: -1..1 scroll position for parallax
   ============================================ */

/* strict paging: one flick moves exactly one compartment */
html {
  scroll-snap-type: y mandatory;
  scroll-behavior: auto; /* smooth-scroll fights the snap engine */
}

.comp {
  position: relative;
  /* lvh, and deliberately not the other two. svh is the height with the
     browser chrome expanded, so once iOS retracts the address bar the
     panel stops short and the next compartment shows along the bottom
     edge. dvh closes that gap but changes value while the chrome moves,
     and a panel that resizes mid-scroll fights mandatory snap: the flick
     sticks between panels. lvh is the retracted height, a fixed number
     that never changes during a scroll, so the panel is never shorter
     than the screen and the snap has a stable target. The cost is that
     while the address bar is showing the panel runs slightly past the
     fold, which resolves the moment the user scrolls. */
  min-height: 100vh;
  min-height: 100lvh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* ---------- intro compartment ---------- */
.comp-intro {
  flex-direction: column;
  text-align: center;
  padding: 130px 24px 70px;
}
.comp-intro h1 {
  font-size: clamp(36px, 5.6vw, 64px);
  margin-bottom: 20px;
  max-width: 700px;
}
.intro-sub {
  color: var(--text-dim);
  max-width: 580px;
  font-size: 17px;
  margin-bottom: 26px;
}
.intro-count {
  font-size: 13px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.scroll-hint {
  margin-top: 48px;
  width: 42px;
  height: 42px;
  border: 1px solid var(--border-hover);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--gold);
  animation: hintBob 2.2s ease-in-out infinite;
}
@keyframes hintBob {
  0%, 100% { transform: translateY(0); opacity: 0.7; }
  50% { transform: translateY(9px); opacity: 1; }
}

/* ---------- shared book-compartment layout ---------- */
.comp-bg {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at 78% 18%, var(--bk-accent-faint), transparent 55%),
    linear-gradient(180deg, var(--bk-bg-top), var(--bk-bg-bottom));
}
.comp-watermark {
  position: absolute;
  right: -1vw;
  bottom: -8vh;
  font-family: var(--bk-font, var(--font-display));
  font-size: 46vh;
  line-height: 1;
  color: var(--bk-accent);
  opacity: 0.07;
  user-select: none;
}

.comp-inner {
  position: relative;
  width: 100%;
  max-width: 1080px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(34px, 6vw, 84px);
  padding: 96px 28px 56px;
}

.comp-meta { max-width: 430px; }
.comp-eyebrow { color: var(--bk-accent); }
.comp-meta h2 {
  font-family: var(--bk-font, var(--font-display));
  color: var(--bk-text);
  font-size: clamp(27px, 3.4vw, 42px);
  line-height: 1.18;
  margin: 4px 0 14px;
}
.comp-meta p {
  color: var(--bk-muted);
  font-size: 16px;
  line-height: 1.6;
  margin-bottom: 28px;
}
.comp-cta {
  display: inline-block;
  padding: 14px 34px;
  border: 1px solid var(--bk-accent);
  border-radius: 2px;
  color: var(--bk-accent);
  text-decoration: none;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: background-color 0.3s, color 0.3s, transform 0.3s;
}
.comp-cta:hover,
.comp-cta:focus-visible {
  background: var(--bk-accent);
  color: var(--bk-bg-bottom);
  transform: translateY(-2px);
}

/* ---------- the stage (book pedestal) ---------- */
.stage {
  position: relative;
  width: clamp(240px, 28vw, 330px);
  flex-shrink: 0;
}
.stage-tilt {
  transform-style: preserve-3d;
  will-change: transform; /* keep the tilt on its own GPU layer */
}

/* grounding shadow: static layer, opacity-only changes */
.stage::after {
  content: "";
  position: absolute;
  left: 8%;
  right: 8%;
  bottom: -26px;
  height: 30px;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.55), transparent 70%);
  filter: blur(9px);
  opacity: 0.55;
  transition: opacity 0.5s;
  pointer-events: none;
}
.comp.active .stage::after { opacity: 0.9; }

/* cover shells share fixed geometry, no layout shift */
.book3d,
.book-cover {
  aspect-ratio: 2 / 3;
  width: 100%;
  position: relative;
  transform-style: preserve-3d;
}
.book-cover { overflow: hidden; border-radius: 7px; }
.cover-img,
.book-cover picture,
.book-face picture {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* typographic stand-in cover */
.cover-art {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 22px 20px;
  background:
    radial-gradient(ellipse at 30% 12%, rgba(255, 255, 255, 0.08), transparent 55%),
    linear-gradient(180deg, var(--bk-bg-top), var(--bk-bg-bottom));
  border: 1px solid var(--bk-accent-soft);
  border-radius: inherit;
}
.cover-brand {
  font-size: 9px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--bk-accent);
}
.cover-title {
  font-family: var(--bk-font, var(--font-display));
  font-size: clamp(19px, 2vw, 24px);
  line-height: 1.3;
  color: var(--bk-text);
  transform: translateY(calc(var(--scrollp, 0) * -10px));
}
.cover-num {
  align-self: flex-end;
  font-family: var(--bk-font, var(--font-display));
  font-size: 14px;
  color: var(--bk-accent);
  border-top: 1px solid var(--bk-accent-soft);
  padding-top: 9px;
  width: 100%;
  text-align: right;
}

/* ---------- shared entrance: swipe from the right + fade ---------- */
.stage {
  opacity: 0;
  transform: translateX(15vw);
  transition:
    transform 0.7s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.45s ease-out;
}
.comp-meta {
  opacity: 0;
  transform: translateX(52px);
  transition:
    transform 0.65s cubic-bezier(0.22, 1, 0.36, 1) 0.18s,
    opacity 0.5s ease-out 0.18s;
}
.comp.shown .stage,
.comp.shown .comp-meta {
  opacity: 1;
  transform: none;
}

/* ============================================
   Book 1: Shelf Book (navy, serif)
   Swings in rotated hard, settles on the shelf;
   centre-stage opens it toward the reader.
   ============================================ */
.fx-shelf .book3d {
  transform: perspective(1100px) rotateY(-58deg);
  transition: transform 0.95s cubic-bezier(0.22, 1, 0.36, 1) 0.05s;
}
.comp.shown.fx-shelf .book3d {
  transform: perspective(1100px) rotateY(-17deg);
}
.comp.shown.fx-shelf.active .book3d {
  transform: perspective(1100px) rotateY(-6deg) translateY(-10px);
}

.fx-shelf .book-face {
  position: absolute;
  inset: 0 13px 0 0;
  border-radius: 7px 2px 2px 7px;
  overflow: hidden;
  background: linear-gradient(180deg, var(--bk-bg-top), var(--bk-bg-bottom));
}
/* spine strip on the trailing edge reads as the book's depth */
.fx-shelf .book-spine {
  position: absolute;
  top: 1px;
  bottom: 1px;
  right: 0;
  width: 13px;
  background: linear-gradient(90deg, var(--bk-bg-bottom), #060f18);
  border-radius: 0 3px 3px 0;
  border-left: 1px solid rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.fx-shelf .book-spine span {
  writing-mode: vertical-rl;
  font-family: var(--bk-font, serif);
  font-size: 8px;
  letter-spacing: 0.12em;
  color: var(--bk-accent);
  white-space: nowrap;
  opacity: 0.8;
}

/* gold rim-light: sweeps on centre-stage arrival and once every
   ~7s while resting, so the cover keeps catching the light */
.fx-shelf .book-rim {
  position: absolute;
  top: -10%;
  bottom: -10%;
  left: 0;
  width: 46%;
  background: linear-gradient(105deg, transparent 8%, var(--bk-accent-soft) 50%, transparent 92%);
  /* parked fully clear of the cover, the skew's top corner
     otherwise pokes back into view at the top-left */
  transform: translateX(-180%) skewX(-16deg);
  animation: rimSweep 7s linear infinite;
  pointer-events: none;
}
@keyframes rimSweep {
  0%, 78% { transform: translateX(-180%) skewX(-16deg); }
  92%, 100% { transform: translateX(340%) skewX(-16deg); }
}
.comp.fx-shelf.active .book-rim {
  animation: rimSweep 2.6s linear infinite;
}

/* ============================================
   Book 3: Lift-off (light cobalt, minimal)
   Rises into frame from below; centre-stage lifts
   it off the ground with the glow underneath.
   ============================================ */
.fx-lift .stage {
  transform: translateY(16vh) scale(0.94);
}
.comp.shown.fx-lift .stage {
  transform: none;
}
.fx-lift .book-cover {
  transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
  animation: bkFloat 6s ease-in-out infinite;
}
.comp.fx-lift.active .book-cover {
  transform: translateY(-16px) scale(1.03);
}
@keyframes bkFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-4px); }
}

.bk-glow {
  position: absolute;
  left: 8%;
  right: 8%;
  bottom: -20px;
  height: 46px;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, color-mix(in srgb, var(--bk-accent) 65%, transparent), transparent 72%);
  filter: blur(16px);
  opacity: 0;
  transition: opacity 0.5s;
  pointer-events: none;
}
.comp.fx-lift.active .bk-glow { opacity: 1; }

.fx-lift .cover-art { border-color: rgba(27, 69, 216, 0.25); }
.fx-lift .bk-spark {
  position: absolute;
  top: 16px;
  right: 16px;
  color: var(--bk-accent);
  font-size: 19px;
  animation: sparkTwinkle 4.5s ease-in-out infinite;
}
@keyframes sparkTwinkle {
  0%, 84%, 100% { transform: scale(1); opacity: 1; }
  92% { transform: scale(1.7) rotate(20deg); opacity: 0.55; }
}

/* ============================================
   Book 4: The Rising Curve (emerald)
   Curve draws itself on every section entry;
   centre-stage ignites the endpoint node.
   ============================================ */
.fx-curve .curve {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.fx-curve .curve-path {
  fill: none;
  stroke: var(--bk-accent);
  /* 27 in the cover's 1800-wide space, which lands at about 5px on a
     330px card. The old value of 3 was tuned for the 200-wide stand-in
     viewBox; carried over unchanged it would render under 2px. */
  stroke-width: 27;
  stroke-linecap: round;
  stroke-dasharray: var(--len, 400);
  stroke-dashoffset: var(--len, 400);
}
.comp.shown.fx-curve .curve-path {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1.15s ease-out 0.35s;
}
.fx-curve .node {
  fill: var(--bk-accent);
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}
.comp.shown.fx-curve .node {
  opacity: 1;
  transition: opacity 0.3s 1.4s;
  animation: nodePulse 0.8s ease-out 1.45s;
}
@keyframes nodePulse {
  0% { transform: scale(1); }
  45% { transform: scale(1.9); }
  100% { transform: scale(1); }
}
.fx-curve .node-glow {
  fill: var(--bk-accent-soft);
  opacity: 0;
  transition: opacity 0.5s 1.4s;
}
.comp.shown.fx-curve .node-glow { opacity: 0.3; }
.comp.shown.fx-curve.active .node-glow {
  opacity: 0.7;
  transition-delay: 0s;
}

/* ============================================
   Book 2: The Grid Pays Out (wine)
   Effects are keyed by fx- class, not by position, so
   this file runs shelf, lift, curve, grid: books 1, 3,
   4, 2. Reordering the series renumbers these labels
   but must not reorder the blocks.

   The cover prints a 3x3 grid running dark wine to
   gold. Centre-stage sends a gold highlight down its
   diagonal, one tile at a time. The .tile rules below
   drove the typographic stand-in that the real artwork
   replaced; they are kept for any book that ships
   without a cover.
   ============================================ */
.grid-cover {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 9px;
  padding: 18px;
  overflow: visible;
  background: linear-gradient(180deg, var(--bk-bg-top), var(--bk-bg-bottom));
  border: 1px solid var(--bk-accent-soft);
  border-radius: 7px;
}
.tile {
  position: relative;
  border-radius: 4px;
  background: var(--tile-c);
  opacity: 0;
  transform: translateY(26px);
  transition:
    transform 0.5s cubic-bezier(0.22, 1, 0.36, 1) var(--rd),
    opacity 0.4s ease-out var(--rd);
}
.comp.shown .tile {
  opacity: 1;
  transform: translateZ(calc(var(--lift) * 0.2));
}
.comp.shown.fx-grid.active .tile {
  transform: translateZ(var(--lift));
}
/* one pre-set shadow + one gold overlay per tile, opacity only */
.tile::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 10px 18px rgba(0, 0, 0, 0.45);
  opacity: 0.3;
  transition: opacity 0.45s var(--rd);
}
.tile::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--bk-accent);
  opacity: 0;
  transition: opacity 0.45s var(--rd);
}
.comp.fx-grid.active .tile::before { opacity: 0.7; }
.comp.fx-grid.active .tile::after { opacity: 0.85; }

/* Nine cells laid over the tiles printed on the real cover. Geometry
   comes from js/books.js, measured off the artwork; the cells are near
   perfect squares, so a 10% radius matches the printed corners at any
   size. Opacity only, and only while the book is centre-stage. */
.grid-pay {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.pay-cell {
  position: absolute;
  border-radius: 10%;
  background: var(--bk-accent);
  opacity: 0;
}
.comp.fx-grid.active .pay-cell {
  animation: gridPay 3.6s ease-in-out var(--pd, 0ms) infinite;
}
@keyframes gridPay {
  0%, 8% { opacity: 0; }
  14% { opacity: 0.8; }
  30%, 100% { opacity: 0; }
}

/* ============================================
   Bundle compartment
   ============================================ */
.bundle-bg {
  background:
    radial-gradient(ellipse at 50% 110%, rgba(212, 175, 55, 0.16), transparent 60%),
    linear-gradient(180deg, #0b0b0e, #060607);
}
.bundle-minis {
  display: flex;
  gap: 14px;
  perspective: 700px;
  flex-shrink: 0;
}
.mini {
  width: 70px;
  aspect-ratio: 2 / 3;
  border-radius: 5px;
  background: linear-gradient(180deg, var(--mtop), var(--mbot));
  border: 1px solid rgba(255, 255, 255, 0.16);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 8px;
  font-family: var(--font-display);
  font-size: 13px;
  color: var(--macc);
  transform: rotateY(calc((var(--mi) - 1.5) * -13deg)) translateY(40px);
  opacity: 0;
  transition:
    transform 0.7s cubic-bezier(0.22, 1, 0.36, 1) calc(var(--mi) * 110ms),
    opacity 0.5s ease-out calc(var(--mi) * 110ms);
}
.comp.shown .mini {
  opacity: 1;
  transform: rotateY(calc((var(--mi) - 1.5) * -13deg)) translateY(0);
  animation: miniBob 5.5s ease-in-out calc(var(--mi) * 0.6s) infinite;
}
@keyframes miniBob {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 -6px; }
}
.bundle-meta h2 { font-family: var(--font-display); font-size: clamp(28px, 4vw, 44px); margin: 4px 0 14px; }
.bundle-meta p { color: var(--text-dim); font-size: 16px; margin-bottom: 28px; max-width: 400px; }

/* ---------- tail (guarantee + footer) ---------- */
.comp-tail {
  /* see the note in home.css: auto let this fall short of a tall window
     and the compartment above showed at the top */
  min-height: 100vh;
  min-height: 100lvh;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  padding-top: 70px;
}
.comp-tail .footer { margin-top: auto; }

/* The tail is the one compartment taller than a screen, and it is meant
   to read as an ordinary page: story, guarantees, CTA, footer. Mandatory
   snap fights that, so js/main.js releases the snap once this section has
   landed and restores it when the reader pages back up. snap-stop goes to
   normal so a longer swipe can run into it rather than being halted at
   the top edge. */
.comp-tail { scroll-snap-stop: normal; }

/* The tail has a full-screen minimum so the compartment above cannot
   leak in, and the footer is pinned to the bottom. On a page whose tail
   carries little (the shop's is a 140px guarantee bar) that left all the
   slack in one void above the footer: 335px at 1280x900, 675px at
   1920x1240. Let the content take the free space and sit centred in it,
   so the room reads as breathing space rather than a gap. */
/* Matches the homepage tail's story block, which is styled in
   home.css. The shop page loads books.css instead, so it needs its own
   copy of these three rules. */
.story {
  text-align: center;
  max-width: 620px;
  margin: 0 auto 54px;
}
.story h2 { font-family: var(--font-display); font-size: clamp(26px, 3.4vw, 40px); margin: 6px 0 16px; }
.story p { color: var(--text-dim); font-size: 16px; line-height: 1.7; margin-bottom: 24px; }

.tail-inner {
  max-width: var(--max-w);
  margin: 0 auto 70px;
  padding: 0 24px;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* ---------- responsive ---------- */
@media (max-width: 860px) {
  .comp-inner {
    flex-direction: column;
    text-align: center;
    gap: 30px;
    padding: 92px 24px 48px;
  }
  .comp-meta { max-width: 460px; }
  .comp-meta p { margin-bottom: 22px; }
  .stage { width: min(58vw, 270px); }
  .comp-watermark { font-size: 34vh; bottom: -4vh; }
  .bundle-minis { justify-content: center; }
  .comp-meta h2 { font-size: clamp(24px, 6vw, 32px); }
}

@media (max-height: 700px) and (max-width: 860px) {
  .stage { width: min(46vw, 220px); }
  .comp-meta h2 { font-size: 22px; }
  .comp-meta p { font-size: 14px; }
}

/* ============================================
   Reduced motion: no choreography, no snap-lock;
   everything rests in its final, fully-visible state
   (js adds .shown/.active immediately).
   ============================================ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-snap-type: none; }
  .stage,
  .comp-meta,
  .stage-tilt,
  .book3d,
  .book-cover,
  .book-rim,
  .bk-spark,
  .bk-glow,
  .tile,
  .tile::before,
  .tile::after,
  .pay-cell,
  .mini,
  .scroll-hint,
  .fx-curve .curve-path,
  .fx-curve .node,
  .fx-curve .node-glow {
    transition: none !important;
    animation: none !important;
  }
  .comp.shown.fx-curve .curve-path { stroke-dashoffset: 0; }
}

/* final-sale disclosure under the bundle CTA */
.bundle-note {
  margin: 14px 0 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--text-dim);
  max-width: 380px;
}

/* ============================================
   Bundle ladder: three tiers, compared side by side
   A buyer comparing three options needs to scroll freely rather
   than one flick per screen, and it does. But that is js/main.js
   releasing the snap because this section is taller than the
   screen, not this rule.
   It used to say scroll-snap-align:none for the same goal, which
   backfired: under mandatory snap, a section with no snap point
   is not free, it is unreachable. This one starts at 4220 with
   the next point at 6157, so every scroll down from the last book
   fell in the dead zone and snapped straight back. The pricing
   ladder could not be reached by scrolling down at all.
   ============================================ */
.comp-bundle {
  scroll-snap-align: start;
  scroll-snap-stop: normal;
  min-height: auto;
  padding: 110px 0 90px;
}

.bundle-wrap {
  position: relative;
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 24px;
}

.bundle-head {
  text-align: center;
  max-width: 620px;
  margin: 0 auto 52px;
}
.bundle-head h2 {
  font-family: var(--font-display);
  font-size: clamp(28px, 4vw, 42px);
  margin-bottom: 14px;
}
.bundle-head p {
  color: var(--text-dim);
  font-size: 16px;
  line-height: 1.65;
}

.bundle-ladder {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  align-items: stretch;
}

.bundle-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 34px 28px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.04);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  transition: border-color 0.3s, transform 0.3s;
}
.bundle-card:hover {
  border-color: var(--border-hover);
  transform: translateY(-4px);
}

.bundle-featured {
  border-color: rgba(212, 175, 55, 0.5);
  background: rgba(212, 175, 55, 0.06);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
}

.bundle-flag {
  position: absolute;
  top: -11px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--gold);
  color: #0a0a0a;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 5px 14px;
  border-radius: 2px;
  white-space: nowrap;
}

.bundle-kicker {
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 12px;
}
.bundle-card h3 {
  font-family: var(--font-display);
  font-size: 22px;
  line-height: 1.2;
  margin-bottom: 10px;
}
.bundle-hook {
  color: var(--text);
  font-size: 15px;
  font-style: italic;
  margin-bottom: 20px;
}

.bundle-price {
  display: flex;
  align-items: baseline;
  gap: 11px;
  margin-bottom: 20px;
}
.bundle-price .now {
  font-family: var(--font-display);
  font-size: 38px;
  color: var(--gold);
  line-height: 1;
}
.bundle-price .was {
  color: var(--text-dim);
  text-decoration: line-through;
  font-size: 16px;
}

.bundle-list {
  list-style: none;
  margin: 0 0 26px;
  padding: 0;
  flex: 1;
}
.bundle-list li {
  position: relative;
  padding: 8px 0 8px 22px;
  font-size: 14px;
  color: var(--text-dim);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.bundle-list li::before {
  content: "✦";
  position: absolute;
  left: 0;
  color: var(--gold);
  font-size: 10px;
}

.bundle-card .btn {
  text-align: center;
  width: 100%;
}

.bundle-note {
  margin: 34px auto 0;
  max-width: 520px;
  text-align: center;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-dim);
}

@media (max-width: 900px) {
  .bundle-ladder { grid-template-columns: 1fr; max-width: 420px; margin: 0 auto; }
  /* the best value tier leads on a phone, where nobody scrolls sideways */
  .bundle-featured { order: -1; }
  .comp-bundle { padding: 80px 0 70px; }
  .bundle-head { margin-bottom: 38px; }
}

/* price and dual action on each shelf card, so a visitor meets a
   number and a free sample without leaving the shop page */
.comp-price {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0 0 22px;
}
/* --bk-*, not --c-*: the --c-* set is defined inline on the homepage
   compartments only. Book compartments are built by js/books.js, which
   sets --bk-*, so --c-accent resolved to nothing here and the colour
   fell back to the inherited near-white. On book 03's light shelf that
   put the price at 1.07:1, effectively invisible. */
.comp-price .now {
  font-family: var(--font-display);
  font-size: 34px;
  line-height: 1;
  color: var(--bk-accent);
}
.comp-price .was {
  font-size: 15px;
  color: var(--bk-muted);
  text-decoration: line-through;
}

.comp-actions {
  display: flex;
  gap: 11px;
  flex-wrap: wrap;
}
.comp-cta-ghost {
  background: transparent;
  border-color: var(--bk-muted);
  color: var(--bk-muted);
}
.comp-cta-ghost:hover,
.comp-cta-ghost:focus-visible {
  background: transparent;
  border-color: var(--bk-accent);
  color: var(--bk-accent);
}

@media (max-width: 900px) {
  .comp-price { justify-content: center; margin-bottom: 16px; }
  .comp-price .now { font-size: 28px; }
  .comp-actions { justify-content: center; }
  .comp-actions .comp-cta { padding: 12px 22px; font-size: 12px; }
}

/* The price row and the second action added height. Claw it back on
   phones so each book still lands inside one snapped screen. */
@media (max-width: 900px) {
  #book-comps .comp-inner { padding-top: 84px; padding-bottom: 40px; gap: 20px; }
  #book-comps .comp-meta p { font-size: 15px; margin-bottom: 16px; }
  #book-comps .stage { width: min(52vw, 210px); }
}
/* Measured at 360x640: the compartment came to 695px of content and the
   Read Chapter One link sat at 655px. These panels snap and do not scroll
   inside themselves, so anything past the fold is unreachable, not just
   below. Trimmed until the second button clears. */
@media (max-height: 700px) and (max-width: 900px) {
  #book-comps .stage { width: min(42vw, 170px); }
  #book-comps .comp-meta h2 { font-size: 22px; }
  #book-comps .comp-inner { padding-top: 62px; padding-bottom: 22px; gap: 12px; }
  #book-comps .comp-meta p { font-size: 14px; margin-bottom: 12px; }
  #book-comps .comp-eyebrow { margin-bottom: 4px; }
  #book-comps .comp-price { margin-bottom: 12px; }
  #book-comps .comp-price .now { font-size: 26px; }
}

/* Real covers need a frame the typographic stand-ins never did. Book 3 is
   the only light cover, so on a near-black page it would otherwise read as
   a bright rectangle with no edge. Framing all four keeps the shelf even,
   and the light one gets a slightly stronger edge so it still sits on the
   page rather than floating over it. */
.book-cover picture,
.book-face picture,
.book3d picture {
  border-radius: inherit;
  overflow: hidden;
}
.cover-img {
  border-radius: inherit;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.14),
    inset 0 0 60px rgba(0, 0, 0, 0.2);
}
/* The one light cover, on a light compartment. An inset hairline is
   invisible against a pale background, so it needs a real edge and a
   shadow to sit on the page instead of dissolving into it. */
.fx-lift .book-cover {
  box-shadow:
    0 18px 50px rgba(27, 69, 216, 0.18),
    0 3px 10px rgba(18, 26, 43, 0.12);
}
.fx-lift .cover-img {
  box-shadow: inset 0 0 0 1px rgba(27, 69, 216, 0.28);
}
.comp.fx-lift.active .book-cover {
  box-shadow:
    0 30px 70px rgba(27, 69, 216, 0.26),
    0 4px 12px rgba(18, 26, 43, 0.14);
}
