/**
 * @file        book-detail.css
 * @description The five bands of the book detail page, including the compact
 *              practitioner band that makes R05's ordering survive 375px
 *
 * @author      Thomas Dobler - SYNTHETIXMIND LTD
 * @email       tom@synthetixmind.com
 * @company     SYNTHETIXMIND LTD, Paphos, Cyprus
 * @url         https://synthetixmind.com
 *
 * @uid         a2f60d38-7195-4e4b-b8c0-3d97e1a4f52c
 * @version     0.3.0.5
 * @created     2026-09-11
 * @updated     2026-09-17
 *
 * @copyright   (c) 2026 by SYNTHETIXMIND LTD
 * @license     Proprietary — All rights reserved
 */

/* --- Band 1: Hero (FR12, M06) -------------------------------------------- */

.hero__grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}

/* WHY the cover is capped at 200px on mobile: the hero's height is the single
 * biggest contributor to how far the primary retailer button sits down the
 * page. A full-width cover on a 375px viewport pushes the buy band past the
 * one-scroll budget on its own. */
.hero__cover {
  max-width: 200px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-subtle);
}

/* The series line, above the title. Small, spaced and steel rather than gold:
 * it orients, and a gold label here would compete with the CTA that is the only
 * gold thing on the page. */
.hero__series {
  margin: 0 0 var(--space-2);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.hero__title {
  margin-bottom: var(--space-2);
  font-size: var(--text-3xl);
}

/* The one page on the site whose subject IS its heading, so it gets display
 * size - but only where the 375px budget is not being spent. */
@media (min-width: 64rem) {
  .hero__title { font-size: var(--text-4xl); }
}

.hero__subtitle {
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  color: var(--text-secondary);
  margin-bottom: var(--space-4);
}

.hero__author {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  margin-bottom: var(--space-4);
}

/* A standfirst rather than a paragraph: serif, italic, one notch up. It is the
 * publisher's line about the book and should not look like the description. */
.hero__tagline {
  font-family: var(--font-heading);
  font-style: italic;
  font-size: var(--text-lg);
  line-height: var(--leading-tight);
  color: var(--text-secondary);
  max-width: var(--measure);
  margin-bottom: var(--space-4);
}

@media (min-width: 64rem) {
  .hero__tagline {
    font-size: var(--text-xl);
    margin-bottom: var(--space-5);
  }
}

/* The bordered card the reference design leads with. Gold rule on the leading
 * edge, raised surface, so the publisher's argument for the book is visibly a
 * pull-quote rather than more body text.
 *
 * ON CONTRAST: this sits on band--page (Cloud White) and the card's own surface
 * is --surface-raised (#FFFFFF), so the text inside it gains headroom rather
 * than losing it - the opposite of the trap the homepage bands hit, where a
 * darkening wash took --text-secondary from 4.54:1 to 4.37:1. */
.hero__why {
  max-width: var(--measure);
}

/* The card treatment starts at 48rem. Below it the padding and border cost
 * ~34px of the 375px budget for decoration, and this field is inside the band
 * the exit gate measures - the template says so in its own comment. */
@media (min-width: 48rem) {
  .hero__why {
    padding: var(--space-4);
    background: var(--surface-raised);
    /* Solid border rather than a gradient background layer - see the note in
     * home.css on why that pattern was abandoned. */
    border: 1px solid var(--border-subtle);
    border-left: 3px solid var(--color-golden-accent);
    border-radius: var(--radius-md);
  }
}

.hero__why > :first-child { margin-top: 0; }
.hero__why > :last-child  { margin-bottom: 0; }

/* The hero follows the masthead directly, so its top padding is doubling a gap
 * the chrome already provides. Trimmed on mobile only, where the 375px exit
 * gate makes every band's padding a real cost: the masthead alone measures
 * 216px at this width, which is the largest single contributor to how far down
 * the page the primary retailer button sits. */
@media (max-width: 47.999rem) {
  .band--page.hero-band { padding-block-start: var(--space-5); }
}

/* --- Breadcrumbs ----------------------------------------------------------
 * The visible counterpart of the BreadcrumbList this page already emits as
 * JSON-LD. Small, quiet, and above the title - it is orientation, not
 * navigation anyone came for. The separator is generated so it is never
 * announced: a screen reader reading "Home slash Books slash" three times a
 * page is noise, and the <ol> already conveys the nesting. */

.crumbs {
  margin-bottom: var(--space-3);
}

/* BELOW 48rem THE CURRENT-PAGE CRUMB IS DROPPED. It is the longest item in the
 * trail, it wraps to a second line in German, and it names the page whose <h1>
 * is the very next thing on screen - so it costs ~22px of the 375px budget to
 * repeat something the reader is already looking at. The trail keeps Home and
 * Books, which are the two that actually navigate.
 *
 * The JSON-LD BreadcrumbList is unaffected and still carries all three levels:
 * a crawler gets the full trail, a phone gets the useful half. */
@media (max-width: 47.999rem) {
  .crumbs__list li:last-child { display: none; }
}

.crumbs__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.crumbs__list li + li::before {
  content: "/";
  margin-right: var(--space-2);
  color: var(--border-subtle);
}

/* The current page is stated, never linked to itself. */
.crumbs__list [aria-current="page"] {
  color: var(--text-secondary);
}

/* THE PLACEHOLDER IS DESKTOP-ONLY, and the number is why. Rendering it on
 * mobile cost 200px and took BOTH locales past the one-scroll gate at a stroke
 * (EN 1077, DE 1224, limit 1000.5) - a regression introduced and measured in
 * the same minute. It carries no information by construction: its alt is empty
 * because it is a generic rectangle, not this book. A real cover still renders
 * at every width; only the stand-in is withheld where space is the constraint. */
@media (max-width: 47.999rem) {
  .hero__cover--placeholder { display: none; }
}

/* --- The hero panel (desktop enhancement) ---------------------------------
 * Below 64rem this is a plain block that follows the text, which is the layout
 * the 375px gate was measured against. The two-column form begins only where
 * vertical space is not the binding constraint.
 *
 * `position: sticky` keeps the cover beside the reader through a long
 * why-it-matters without adding a single pixel to the document height - which
 * matters because document height is exactly what the exit gate measures. */

.hero__panel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
}

/* An anchor to band 3, styled as a quiet control rather than a CTA. It must
 * not read as a buy button: the buy buttons are below the practitioner band by
 * R05, and a gold control here would be that rule defeated by styling. */
/* HIDDEN BELOW 64rem, and this is a budget decision rather than a taste one.
 * On a narrow viewport the buy band is the next thing after the practitioner
 * band, so an anchor pointing at it is redundant - and it is not free: the 44px
 * target plus its gap cost 60px of a budget that German had already overspent.
 * `display: none` also takes it out of the accessibility tree, which is correct
 * here precisely BECAUSE it is redundant: nothing is lost that the very next
 * band does not provide. */
.hero__formats {
  display: none;
}

@media (min-width: 64rem) {
  .hero__formats {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--touch-min);
    font-size: var(--text-sm);
    font-weight: 600;
  }
}

.hero__formats::after {
  content: "\2193";           /* downward arrow - the target is further down */
  font-size: var(--text-base);
}

@media (min-width: 768px) {
  .hero__grid {
    grid-template-columns: 1fr minmax(180px, 260px);
    gap: var(--space-6);
    align-items: start;
  }

  .hero__cover { max-width: 100%; }
}

@media (min-width: 64rem) {
  .hero__grid {
    grid-template-columns: 1fr minmax(240px, 320px);
    gap: var(--space-8);
  }

  /* The panel becomes a card only here, where it has room to be one. */
  .hero__panel {
    position: sticky;
    top: var(--space-5);
    padding: var(--space-5);
    background: var(--surface-raised);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: 0 0.5rem 1.5rem rgb(45 49 66 / 0.08);
    align-items: stretch;
  }

  .hero__panel .hero__cover {
    width: 100%;
    box-shadow: 0 0.5rem 1.25rem rgb(45 49 66 / 0.18);
  }

  .hero__formats {
    justify-content: center;
    border-top: 1px solid var(--border-subtle);
    padding-top: var(--space-4);
  }
}

/* --- Band 2: Practitioner (FR13, R05) ------------------------------------
 *
 * This band sits between the hero and the buy buttons. That ordering is the
 * product thesis, and it is also the project's biggest UX risk (PRD Journey 2:
 * a book buyer must not perceive obstruction).
 *
 * Below --bp-md the band collapses to ONE LINE plus an inline link, ~88–96px,
 * so it costs under one thumb-swipe. The full card appears only where vertical
 * space is not scarce. Ordering is preserved at every viewport; only the
 * treatment changes.
 *
 * ACCEPTANCE TEST: at 375×667 the primary retailer button must be reachable
 * within one scroll. Verified by projectfiles/tests/e2e/book-detail-375.spec.ts.
 */

.practitioner {
  /* Tight block padding is the whole mechanism — do not replace with --space-8. */
  padding-block: var(--space-4);
}

.practitioner__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
}

.practitioner__statement {
  margin: 0;
  font-size: var(--text-base);
}

/* Framed as "this book came out of this practice", never "Book a call now" —
 * the first extends the visitor's catalogue mental model, the second violates
 * it. The copy lives in the translation catalogue; this rule is why. */
.practitioner__link {
  color: var(--text-on-dark);
  font-weight: 600;
}

/* At --bp-md and above there is vertical room for the full card treatment. */
@media (min-width: 768px) {
  .practitioner {
    padding-block: var(--space-6);
  }

  .practitioner__inner {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: var(--space-5);
  }

  .practitioner__statement {
    font-size: var(--text-lg);
    max-width: var(--measure);
  }
}

/* --- Band 3: Buy (FR14–FR17) ---------------------------------------------
 * The buy affordance must be visible in its expected form — recognisable
 * buttons with retailer names — so the catalogue model is confirmed rather
 * than frustrated. */

.buy__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.buy__item { margin: 0; }

/* --- Format cards ---------------------------------------------------------
 * The reference design presents each edition as a card rather than a loose
 * button, which is what makes "hardcover / ebook / audio" read as a choice of
 * FORMAT instead of a row of identical links.
 *
 * The card is the <li>; the button inside keeps every attribute the buy band
 * depends on - data-primary, the analytics hooks, .button--primary. Nothing
 * here changes what is clicked or what is measured, only what it sits in.
 *
 * Applied to the VISIBLE list only. The items behind `details.buy__more` stay
 * plain buttons: they are the remainder, and giving them equal visual weight
 * is how FR16's primary emphasis quietly disappears. */
.buy__item--card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-4);
  background: var(--surface-page);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

/* The primary edition is the one with the gold leading edge, matching the
 * hero's why-it-matters card and the homepage event cards. Fill and weight
 * still carry the emphasis on the button itself (NFR21) - this is additive. */
.buy__item--card:has(.buy__button--primary) {
  background: var(--surface-raised);
  border-left: 3px solid var(--color-golden-accent);
}

@media (min-width: 48rem) {
  .buy__list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    align-items: stretch;
  }

  /* Inside a grid the card should fill its track, and the button should fill
   * the card, so the row reads as equal-weight options of differing rank. */
  .buy__item--card { height: 100%; }
  .buy__item--card > .button { width: 100%; }
}

/* FR16: the primary platform is emphasised over secondaries. The emphasis is
 * carried by fill + weight, not by colour alone (NFR21). */
.buy__button--primary {
  font-size: var(--text-lg);
}

.buy__format {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  display: block;
  margin-top: var(--space-1);
}

/* FR15: remaining platforms behind a toggle. <details> is used rather than a
 * scripted disclosure so the control works with JavaScript disabled (NFR28).
 * FR14 is satisfied because the PRIMARY button is never inside this element. */
.buy__more {
  margin-top: var(--space-4);
}

.buy__more > summary {
  cursor: pointer;
  min-height: var(--touch-min);
  display: flex;
  align-items: center;
  color: var(--text-link);
  font-weight: 600;
}

.buy__more[open] > summary {
  margin-bottom: var(--space-3);
}

/* --- Band 4: Detail (FR19) ----------------------------------------------- */

.detail__description {
  max-width: var(--measure);
}

/* --- Table of contents ----------------------------------------------------
 * Authored HTML, so this styles whatever list the editor wrote rather than a
 * structure this template controls. Counters are avoided deliberately: an <ol>
 * numbers itself, and the homepage already recorded what happens when a page
 * depends on CSS counters in a browser that does not implement them. */

.detail__toc {
  max-width: var(--measure);
  margin-bottom: var(--space-6);
  padding: var(--space-4);
  padding-left: var(--space-5);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--color-golden-accent);
  border-radius: var(--radius-md);
}

.detail__toc > h3 {
  margin: 0 0 var(--space-3);
  font-size: var(--text-lg);
}

.detail__toc ol,
.detail__toc ul {
  margin: 0;
  padding-left: var(--space-5);
}

.detail__toc li { margin-bottom: var(--space-2); }
.detail__toc li:last-child { margin-bottom: 0; }

.detail__meta {
  display: grid;
  gap: var(--space-2);
  margin: var(--space-5) 0 0;
  font-size: var(--text-sm);
}

.detail__meta > div {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.detail__meta dt {
  font-weight: 600;
  margin: 0;
}

.detail__meta dd {
  margin: 0;
  color: var(--text-secondary);
}

/* .chip-list and .chip MOVED to components/site-chrome.css on 2026-09-14.
 * They were used by the header, the footer, the article page, the webinar page
 * and components/chips.html.twig, none of which load THIS file - so only the
 * book page ever had chips. Site-wide markup needs a site-wide sheet. */

/* --- Band 5: Recirculation (FR18, FR20) ---------------------------------- */

.recirc__placeholder {
  max-width: var(--measure);
  color: var(--text-secondary);
}

/* --- The cover's hover treatment (Stitch comp, 2026-09-17) ------------------
 *
 * The comp's signature image effect: the jacket tilts a few degrees toward the
 * reader, lifts, and picks up a soft gradient glow behind it and a sheen across
 * its face. It is the one piece of motion on the page that is about the BOOK
 * rather than about a control.
 *
 * WHY IT IS ON THE PANEL AND NOT THE IMAGE. The glow has to sit behind the
 * cover and the sheen in front of it, so both are pseudo-elements of a
 * positioned wrapper. `.hero__panel` already exists and already contains
 * exactly the cover and the formats anchor.
 *
 * ⚠️ IT IS POINTER-ONLY, deliberately. `:hover` on a touch device either never
 * fires or sticks after a tap, and a tilted jacket that stays tilted looks
 * broken. `@media (hover: hover)` is what confines it to devices with a real
 * pointer; the reduced-motion block in base.css collapses the durations for
 * anyone who has asked for less movement, leaving the resting state - which is
 * the untilted, unglowing cover the page has always shown.
 *
 * `will-change` is NOT set. It is a promise to the compositor that costs memory
 * on every book page whether or not anybody hovers, and the transform here is
 * cheap enough that the hint buys nothing measurable.
 */
@media (hover: hover) and (pointer: fine) {
  .hero__panel {
    position: relative;
  }

  /* The glow. Behind everything, and it never intercepts the pointer. */
  .hero__panel::before {
    content: "";
    position: absolute;
    inset: calc(var(--space-4) * -1);
    border-radius: var(--radius-lg);
    background: radial-gradient(
      60% 60% at 30% 20%,
      rgb(191 155 48 / 0.22),
      rgb(122 147 172 / 0.16) 45%,
      transparent 70%
    );
    filter: blur(28px);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-slow) var(--ease-out);
  }

  .hero__panel:hover::before {
    opacity: 1;
  }

  .hero__cover {
    /* The tilt pivots from the spine edge, which is what makes it read as a
       book opening toward the reader rather than a card rotating in place. */
    transform-origin: left center;
    transition: transform var(--duration-slow) var(--ease-out),
                box-shadow var(--duration-slow) var(--ease-out);
  }

  .hero__panel:hover .hero__cover {
    transform: perspective(900px) rotateY(-5deg) rotateX(3deg) translateY(-6px);
    box-shadow: 0 18px 40px rgb(45 49 66 / 0.28);
  }
}
