/* Book card. Two variants from one partial, both from the Figma reference:
   home     node 7:174, 387 x 639, description kept, filled pill action.
   compact  node 25:414 grid, 285 x 524, no description, text action.
   The home card is the default; the parts that differ read the --book-card-*
   properties below, which a compact context sets (see "Compact variant"). */

.book-card {
  display: flex;
  flex-direction: column;
  position: relative;
  height: 100%;
  border-radius: 0;
  box-shadow: none;
}

.book-card__cover {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

/* ---- Home variant ----
   The cover overhangs the tinted surface: white behind the top 59px, then
   --color-surface for the rest of the card. A gradient keeps this to one
   element rather than an extra absolutely-positioned layer. */

.book-card {
  background-image: linear-gradient(
    to bottom,
    var(--color-canvas) 0,
    var(--color-canvas) var(--book-card-overhang, 3.6875rem),
    var(--color-surface) var(--book-card-overhang, 3.6875rem)
  );
}

/* The cover box is sized by WIDTH plus an aspect-ratio, never by a fixed height.
   Deriving the parent's height from the child <img> would be circular — the img
   is sized against this parent — and each cover's intrinsic height would differ,
   so titles would stop lining up across a row. An explicit width with a declared
   ratio gives a deterministic box that still rescales with the viewport.
   `overflow: hidden` is required, not decorative: without it, a flex container's
   automatic minimum size is content-based, so a cover image whose natural ratio
   is narrower than the box (most of ours are) overrides aspect-ratio entirely and
   the box grows to the image's own height instead. */
.book-card__cover-frame {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  box-sizing: content-box;
  width: var(--book-card-cover-width, var(--card-cover-width));
  aspect-ratio: var(--book-card-cover-aspect, var(--card-cover-aspect));
  max-width: 100%;
  padding-top: var(--book-card-cover-inset, 0);
  margin-inline: auto;
}

.book-card__body {
  padding: var(--book-card-body-padding, var(--space-md) 1.875rem var(--space-lg)); /* 30px sides, per Figma */
}

/* ---- Badges ---- */

.book-card__badges {
  position: absolute;
  left: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
}

.book-card__badges {
  top: var(--book-card-badge-top, var(--card-badge-offset));
}

.book-card__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: clamp(5rem, 3.81rem + 4.88vw, 7.5rem); /* 80 -> 120 */
  min-height: 1.875rem; /* 30 */
  padding-inline: var(--space-xs);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-snug);
  text-transform: uppercase;
  color: var(--color-canvas);
}

.book-card__badge--new {
  background-color: var(--color-badge-new);
}

.book-card__badge--sale {
  background-color: var(--color-badge-sale);
}

/* ---- Body ---- */

.book-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  flex: 1;
}

/* Title and author as one block, spaced like the rest of the body (the
   catalog and puzzle cards tighten the body's gap, and this follows). */
.book-card__heading {
  display: flex;
  flex-direction: column;
  gap: inherit;
  margin: 0;
}

/* Figma: card title and price are Raleway 700 / 24, leading 1.17. */
.book-card__title {
  margin: 0;
  font-size: var(--book-card-title-size, var(--font-size-xl));
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
}

/* The whole title is visible (the home offers alone clamp it to two lines,
   home.css). In a grid every title
   keeps one size and the row lines up around the longest (see "Rows that
   line up" below); only a phone, whose cards are too narrow for that, sets a
   title marked --long server-side one step smaller.
   The link is a block so the title's words are its own lines: Chromium skips
   `text-wrap: pretty` (base.css) for text inside an inline box, and a title
   ending on a short word ("Частина I") would leave it alone on the last line. */
.book-card__title a {
  display: block;
  color: var(--color-ink);
  text-decoration: none;
  overflow-wrap: break-word;
}

/* The card is one link, not a stack of them: the title's anchor is stretched
   over the whole tile (which is the card's positioning context), so the cover
   and the space around it open the book without being separate click targets
   of their own. The add-to-cart button sits above it and keeps its own click. */
.book-card__title a::after {
  position: absolute;
  inset: 0;
  content: "";
}

/* Muted, not Figma's light grey: an author is read, and #b7b7b7 on the card
   surface is 1.9:1 (CLAUDE.md, "Figma source-of-truth deviations"). */
.book-card__author {
  margin: 0;
  font-size: var(--font-size-md);
  color: var(--color-muted);
}

.book-card__description {
  margin: 0;
  font-size: var(--font-size-md);
  line-height: var(--line-height-snug);
  color: var(--color-ink);
  display: var(--book-card-description-display, -webkit-box);
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ---- Footer row: price left, action right ---- */

/* Neither child may shrink below its own text: the price and the button label
   must never wrap mid-word. flex-wrap is the release valve — once the row
   truly can't fit both at their natural width, the button drops to its own
   line instead of squeezing, in every language and at every card width. */
.book-card__footer {
  margin-top: auto;
  padding-top: var(--space-md);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2xs);
}

/* The heart and add to cart travel together at the row's end, and keep
   together when a narrow card wraps them under the price. Both sit above the
   card-wide title link, so pressing either never opens the book. */
.book-card__actions {
  position: relative;
  z-index: 1;
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--space-3xs);
  margin-left: auto;
}

/* One action, one appearance: the amber icon circle is identical on the home
   card, the category card and the search card (docs/style-guide.md rule 2, and
   the recorded Figma deviation for node 25:414). Its size and hidden label
   come from the shared primitive in controls.css. */
.book-card__add-to-cart {
  /* Above the card-wide title link, so adding to the cart never opens the book. */
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  gap: var(--space-2xs);
  min-height: var(--action-height);
  border: 0;
  border-radius: var(--radius-pill);
  background-color: var(--color-action);
  color: var(--color-ink);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-bold);
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
  .book-card__title a:hover {
    color: var(--color-action);
  }

  .book-card__add-to-cart:hover {
    filter: brightness(0.95);
  }
}

/* ---- Price ---- */

.price {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
  /* An amount and its currency always read as one unit: "450 грн." never
     breaks across two lines. */
  white-space: nowrap;
}

.price__current {
  font-weight: var(--font-weight-bold);
  font-size: var(--book-card-price-size, var(--font-size-xl));
  color: var(--color-ink);
}

/* A discounted price turns red, with the original struck through above it. */
.price--discounted .price__current {
  color: var(--color-badge-sale);
}

.price__old {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  text-decoration: line-through;
}

/* Stands in the price row of a sold book, on the card and the product page
   alike, so both use this one label. */
.out-of-stock {
  margin: 0;
  font-size: var(--font-size-xs);
  color: var(--color-danger);
}

/* ---- Compact variant ----
   The reduced card of Figma node 25:414: the cover on the tinted surface
   without the white overhang, no short description, a smaller title and
   price. It is the card of a grid of narrow columns: every catalog listing,
   and the home offers on a desktop, four to a row on the catalog's 285 module
   (home.css, which keeps the home card's cover overhang and description there
   and hands the whole home card back below the desktop).

   The catalog context is .catalog-layout rather than a view flag: the native
   AJAX catalog re-renders the card partial without our ViewData, so a
   modifier class would be lost on every filter or page change.

   Its add-to-cart action does NOT follow 25:414: Figma draws that as
   underlined text there and as a filled pill on the home card, which is an
   inconsistency in the source file. One filled amber control wins everywhere
   (CLAUDE.md, "Figma source-of-truth deviations").

   :where() keeps the declaration at zero specificity, so a feature
   stylesheet can hand a context back the home card although this sheet
   loads after it. */
:where(.catalog-layout, .home-curation__grid) {
  --book-card-overhang: 0px;
  --book-card-cover-width: var(--card-cover-catalog-width);
  --book-card-cover-aspect: var(--card-cover-catalog-aspect);
  --book-card-cover-inset: var(--space-2xl);
  --book-card-body-padding: var(--space-md);
  --book-card-badge-top: var(--space-md);
  --book-card-description-display: none;
  --book-card-title-size: var(--font-size-md);
  --book-card-price-size: var(--font-size-md);
}

@media (max-width: 36.25rem) {
  /* The home card's white-to-grey split is a fixed 59px offset (matching
     the Figma badge height), not a percentage - it assumes the desktop
     cover size it was measured against. --card-cover-width's clamp shrinks
     the cover well below that on narrow phones, so the fixed offset now
     lands partway down the (shorter) cover instead of just past its badge,
     leaving the top of the cover on white. Mobile-only, drop the split so
     the surface tint covers the whole card, same as the catalog variant
     already does at every width. Desktop keeps the gradient unchanged. */
  .book-card {
    background-image: none;
    background-color: var(--color-surface);
  }

  /* The action shrinks to an icon-only circle here (controls.css), so price
     and action stay on one row. */
  .book-card__footer {
    flex-wrap: nowrap;
  }

  .book-card__title--long {
    font-size: var(--font-size-md);
  }

  .book-card__badges {
    top: var(--card-badge-offset-compact);
  }
}

/* ---- Rows that line up ----
   In a grid of cards (.book-grid: the catalog and search listings, the home
   offers) each card's parts share their row's tracks through subgrid, so
   every title, description and footer starts level with its neighbours'
   however many lines a title takes, with nothing truncated or padded to a
   guessed length. The author is not a track of its own: it stays right under
   its title, which is what it labels. Five tracks: cover, title and author,
   description, the native add-info widget zone, footer. Parts are placed by
   track rather than by order, so a card with its description hidden keeps
   the rest in line; spacing is margins, not gaps, so an empty track adds
   none. That includes the grid's own row gap, which a subgrid cannot
   take off the tracks no part fills: a book grid declares its gap once as
   --grid-gap and its row gap as var(--grid-row-gap, var(--grid-gap)); here
   the row gap is dropped and each cell carries --grid-gap below itself. The footer fills its track and centres its row, so a sold
   book's label sits on the price line of its neighbours.
   Not on a phone: the home offers are a sideways carousel there, not a grid,
   and two narrow catalog columns keep the plain card. A browser without
   subgrid keeps the plain card too. */
@supports (grid-template-rows: subgrid) {
  @media (min-width: 36.3125rem) {
    .book-grid__cell,
    .book-grid__cell > .book-card,
    .book-grid__cell .book-card__body {
      display: grid;
      grid-template-rows: subgrid;
      row-gap: 0;
    }

    .book-grid {
      --grid-row-gap: 0px;
    }

    .book-grid__cell {
      grid-row: span 5;
      margin-bottom: var(--grid-gap);
    }

    .book-grid__cell > .book-card {
      grid-row: 1 / -1;
    }

    .book-grid__cell .book-card__cover-frame {
      grid-row: 1;
    }

    .book-grid__cell .book-card__body {
      grid-row: 2 / -1;
    }

    /* The body's own gap is off here, so the block sets it outright. */
    .book-grid__cell .book-card__heading {
      grid-row: 1;
      gap: var(--space-2xs);
    }

    .book-grid__cell .book-card__description {
      grid-row: 2;
      margin-top: var(--space-2xs);
    }

    .book-grid__cell .book-card__footer {
      grid-row: 4;
      margin-top: var(--space-2xs);
    }
  }
}
