/*
 * Content sections.
 *
 * One block per section of PRD 7, in the order the page renders them, plus the lightbox
 * that the gallery section opens. Purchase components that are shared between the hero and
 * the offer section are not here, they are in woo.css.
 *
 * Every rule is carried over from prototype/style.css unchanged. The only additions are
 * marked with a comment and named in the handover.
 *
 * Enqueue after base.css.
 */

/* ---------- Section 2: hero ---------- */

.hero {
  padding-block: 40px 64px;
  background: linear-gradient(180deg, var(--bg-light) 0%, var(--surface) 60%);
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: 56px;
  align-items: start;
}

/* ---------- Hero gallery ---------- */

.gallery__main {
  position: relative;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--bg-warm);
  aspect-ratio: 4 / 5;
}

.gallery__main img,
.gallery__main video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The video lies over the first gallery picture and never replaces it, so the picture is the
   poster and costs no second file.

   Transparent until app.js has seen a frame play. A video element with nothing decoded is
   not transparent, it is a black rectangle, and that rectangle would be the hero for as long
   as the file takes to arrive and forever with JavaScript switched off. Opacity and not
   display, because a display:none video is one a browser is allowed to stop decoding.

   pointer-events stay off throughout. The element carries no controls, and an invisible
   control surface over the picture is worse than no control surface. */
.gallery__video {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}

.gallery__video.is-playing {
  opacity: 1;
}

/* Shown only when autoplay did not happen: prefers-reduced-motion, Data Saver, or a browser
   that refused. Same shape as the play button on the content blocks. */
.gallery__play {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 64px;
  height: 64px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  color: var(--ink);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.gallery__play[hidden] {
  display: none;
}

.gallery__play svg {
  width: 24px;
  height: 24px;
  margin-left: 3px;
}

.gallery__badge {
  position: absolute;
  top: 16px;
  left: 16px;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(6px);
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 0.8125rem;
  letter-spacing: 0.01em;
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

/* One row whatever the count, because the video adds a seventh item to a six picture
   gallery. minmax(0, 1fr) is what keeps a long strip from pushing the page sideways. */
.gallery__thumbs {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 10px;
  margin-top: 10px;
}

.thumb {
  position: relative;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: var(--bg-warm);
  cursor: pointer;
  aspect-ratio: 1 / 1;
}

/* The theme's own fallback pictures come wrapped in <picture>, so the WebP can be offered
   with the JPG behind it. <picture> is an inline box of automatic height, and height: 100%
   on the image inside would have nothing to resolve against. The wrapper takes the square. */
.thumb picture {
  display: block;
  width: 100%;
  height: 100%;
}

.thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.thumb[aria-current="true"] {
  border-color: var(--ink);
  box-shadow: 0 0 0 1px var(--ink);
}

/* The video thumbnail is the same picture as the first one in the strip, so the play badge
   is the only thing telling them apart. It has to be unmistakable. */
.thumb__play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(28, 26, 23, 0.32);
  color: #fff;
}

.thumb__play svg {
  width: 18px;
  height: 18px;
  margin-left: 2px;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.4));
}

/* ---------- Hero buy column ---------- */

.buy__title {
  font-size: var(--step-4);
  line-height: 1.12;
  letter-spacing: -0.02em;
  font-weight: 600;
  margin: 0 0 14px;
}

/* Added: the prototype has no subtitle, the content model does (hero_subtitle). */
.buy__subtitle {
  margin: -6px 0 18px;
  color: var(--ink-soft);
  font-size: var(--step-1);
}

.rating {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--step--1);
  color: var(--ink-soft);
  margin-bottom: 22px;
}

.stars {
  display: inline-flex;
  gap: 2px;
  color: var(--wood-mid);
}

.stars svg {
  width: 15px;
  height: 15px;
}

/* An empty star is the same glyph at low opacity, so a 4 of 5 rating still reads as five
   positions instead of four floating shapes. */
.stars .star--empty {
  opacity: 0.28;
}

.usp {
  list-style: none;
  margin: 0 0 26px;
  padding: 0;
  display: grid;
  gap: 11px;
}

.usp li {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: 12px;
  align-items: start;
  font-size: var(--step-0);
  color: var(--ink-soft);
}

.usp svg {
  margin-top: 4px;
  color: var(--wood-dark);
}

.usp strong {
  color: var(--ink);
  font-weight: 600;
}

/* The prototype set this with a style attribute on the button. Inline CSS is not allowed in
   the theme, so the spacing lives with the component it belongs to. */
.buy .add-to-cart-form {
  margin-top: 16px;
}

/* ---------- Section 3: trust strip ---------- */

.trust {
  border-block: 1px solid var(--line);
  background: var(--bg-warm);
}

.trust__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  padding-block: 20px;
}

.trust__item {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-size: var(--step--1);
  color: var(--ink-soft);
  text-align: left;
}

.trust__item svg {
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  color: var(--wood-dark);
}

/* ---------- Section 4: how it works ---------- */

.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
  counter-reset: step;
}

.step {
  position: relative;
}

.step__media {
  border-radius: var(--radius-card);
  overflow: hidden;
  aspect-ratio: 1 / 1;
  background: var(--bg-warm);
  margin-bottom: 18px;
}

.step__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.step__num {
  display: block;
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--wood-dark);
  letter-spacing: 0.08em;
  margin-bottom: 6px;
}

.step__title {
  font-size: var(--step-2);
  font-weight: 600;
  margin: 0 0 6px;
  letter-spacing: -0.01em;
}

.step p {
  margin: 0;
  color: var(--ink-soft);
}

/* ---------- Sections 5 to 8: content blocks ---------- */

.blocks {
  display: grid;
  gap: 88px;
}

.block {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 56px;
  align-items: center;
}

.block--reverse .block__media {
  order: 2;
}

.block__media {
  border-radius: var(--radius-card);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--bg-warm);
}

.block__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The video is square, so it gets its own ratio instead of a cropped 4:3. */
.block__media--video {
  aspect-ratio: 1 / 1;
  position: relative;
}

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

/* The play button only appears when autoplay did not happen. That is the case under
   prefers-reduced-motion and when the browser refuses autoplay. */
.block__play {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 68px;
  height: 68px;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.92);
  color: var(--ink);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.18);
}

.block__play[hidden] {
  display: none;
}

.block__play svg {
  width: 28px;
  height: 28px;
  margin-left: 3px;
}

.block__play:hover {
  background: #fff;
}

.block__text h2 {
  font-size: var(--step-3);
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-weight: 600;
  margin: 0 0 14px;
}

.block__text p {
  margin: 0 0 12px;
  color: var(--ink-soft);
  font-size: var(--step-1);
}

.block__note {
  font-size: var(--step--1) !important;
  color: var(--ink-muted) !important;
  border-left: 2px solid var(--wood-light);
  padding-left: 12px;
}

/* ---------- Section 9: specs ---------- */

.specs {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: 56px;
  align-items: start;
}

.specs__intro .section__title {
  text-align: left;
}

.specs__intro .section__lead {
  text-align: left;
}

.specs__list {
  margin: 0;
  border-top: 1px solid var(--line);
}

.specs__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: 24px;
  padding: 15px 0;
  border-bottom: 1px solid var(--line);
}

.specs__row dt {
  color: var(--ink-muted);
  font-size: var(--step--1);
  letter-spacing: 0.02em;
}

.specs__row dd {
  margin: 0;
  font-weight: 500;
}

/* ---------- Section 10: gallery ---------- */

.gallery-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}

.gallery-grid__item {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  border-radius: var(--radius-card);
  overflow: hidden;
  aspect-ratio: 1 / 1;
  background: var(--bg-warm);
  cursor: zoom-in;
}

.gallery-grid__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}

.gallery-grid__item:hover img {
  transform: scale(1.03);
}

/* ---------- Section 11: reviews ---------- */

.reviews {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

.review {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.review__photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--bg-warm);
}

.review__body {
  padding: 18px 20px 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}

.review__stars {
  color: var(--wood-mid);
  letter-spacing: 2px;
  font-size: var(--step--1);
}

.review__body p {
  margin: 0;
  color: var(--ink-soft);
  flex: 1;
}

.review__author {
  font-size: var(--step--1);
  font-weight: 600;
}

/* The external platform aggregate. Empty in phase one, so this only ever paints once
   Trustpilot or an equivalent is actually in place. */
.platform-score {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin: 0 0 32px;
  font-size: var(--step--1);
  color: var(--ink-soft);
}

.platform-score a {
  color: inherit;
}

.buy .platform-score {
  justify-content: flex-start;
  margin: 16px 0 0;
}

/* One <symbol> definition for the forty odd ratings in the text list below. It has to stay in
   the layout tree, not display:none, or the <use> references have nothing to point at. */
.reviews__sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* The reviews past the sixth. The same grid, so this needs almost nothing.

   The whole point of the second list is that it is not a second design. It inherits .reviews
   and .review untouched, which is what keeps the border, the radius, the padding and, more
   importantly, the equal card heights inside a row: the cards are grid items, grid items
   stretch, and .review__body p already takes the spare space so the name sits on the bottom
   edge whatever the quote does. A row of three cannot come out ragged.

   The only rule needed is the seam. The margin equals the grid gap exactly, so two stacked
   grids read as one continuous grid rather than as two blocks. Six featured and six per press
   are whole rows at three, two and one across, so the seam never lands inside a row. */
.reviews--more {
  margin-top: 24px;
}

/* A floor under the card, not a change of style.

   A card with no picture is as tall as its quote, and a row of three one line reviews would
   come out as a strip of three shallow boxes under two rows of tall ones. This gives the body
   the height of roughly four lines to fill, which is where most of these reviews land anyway,
   so it does nothing at all to a normal card and only catches the very short ones.

   The owner's instruction was one presentation, not two, so there is deliberately nothing
   else here. No wider padding, no larger quote, no accent. Those were the tempting way to
   stop a photoless row looking bare, and every one of them is the first step back to the two
   different displays that got the last version rejected. A card carries its own weight
   through the border and the whitespace it already has. */
.review--text .review__body {
  min-height: 132px;
}

/* The last press of the button removes the button, so focus is moved into the first review
   that press revealed. This is what tells the visitor where they landed. :focus and not
   :focus-visible: the element is only ever focused programmatically, and browsers do not
   treat that as visible focus, which would leave the move silent. */
.review--text:focus {
  outline: 2px solid var(--wood-dark);
  outline-offset: 4px;
}

/* Two controls, one appearance.

   The <summary> is what works without JavaScript and the <button> is what replaces it when
   app.js runs. They are styled identically and sized identically so that the swap costs no
   height and shifts nothing, whichever one the visitor ends up with. */
.reviews-more__summary,
.reviews-more__btn {
  display: block;
  width: fit-content;
  margin: 28px auto 0;
  padding: 14px 28px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  list-style: none;
}

.reviews-more__summary::-webkit-details-marker {
  display: none;
}

/* The display above is what makes the button a centred block, and it also beats the browser's
   own [hidden] { display: none }, which is one line and no specificity at all. Without this
   rule the button PHP printed hidden is on the screen next to the summary for anybody whose
   script never loaded, which is two controls for one job. Caught on the live page, not here. */
.reviews-more__btn[hidden] {
  display: none;
}

.reviews-more__summary:hover,
.reviews-more__btn:hover {
  border-color: var(--wood-mid);
  background: var(--bg-light);
}

.reviews-more__summary:focus-visible,
.reviews-more__btn:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* Without JavaScript the summary is a toggle, so it has to look like one once it is open,
   otherwise "Read 44 more reviews" sits above the 44 reviews it already opened and reads as a
   button that did nothing. Same plus and minus the FAQ uses, for the same reason. */
.reviews-more__summary::after {
  content: " +";
  color: var(--wood-dark);
  font-weight: 400;
}

.reviews-more[open] > .reviews-more__summary::after {
  content: " \2212";
}

.reviews__note {
  margin: 28px auto 0;
  max-width: 620px;
  text-align: center;
  font-size: 0.8125rem;
  color: var(--ink-muted);
}

/* ---------- Section 12: FAQ ---------- */

.faq {
  max-width: 760px;
}

.faq__item {
  border-bottom: 1px solid var(--line);
}

.faq__item:first-of-type {
  border-top: 1px solid var(--line);
}

.faq__item summary {
  cursor: pointer;
  list-style: none;
  padding: 20px 44px 20px 0;
  font-size: var(--step-1);
  font-weight: 500;
  position: relative;
}

.faq__item summary::-webkit-details-marker {
  display: none;
}

.faq__item summary::after {
  content: "+";
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--step-2);
  font-weight: 400;
  color: var(--wood-dark);
  line-height: 1;
}

.faq__item[open] summary::after {
  content: "\2212";
}

.faq__item summary:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.faq__answer {
  padding: 0 44px 22px 0;
  color: var(--ink-soft);
}

.faq__answer p {
  margin: 0 0 12px;
}

.faq__answer p:last-child {
  margin-bottom: 0;
}

/* ---------- Section 13: offer ---------- */

.offer__inner {
  max-width: 620px;
}

.offer .qty {
  background: var(--bg-light);
}

.offer .price {
  justify-content: center;
}

/* ---------- Section 14: guarantees ---------- */

.guarantees {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 28px;
}

.guarantee-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 28px 26px;
}

.guarantee-card svg {
  width: 26px;
  height: 26px;
  color: var(--wood-dark);
  margin-bottom: 14px;
}

.guarantee-card h3 {
  font-size: var(--step-1);
  font-weight: 600;
  margin: 0 0 8px;
}

.guarantee-card p {
  margin: 0;
  color: var(--ink-soft);
  font-size: var(--step--1);
}

/* ---------- Lightbox, opened from the gallery ---------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(20, 16, 12, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 64px;
}

.lightbox[hidden] {
  display: none;
}

.lightbox__img {
  max-width: 100%;
  max-height: 100%;
  border-radius: 8px;
  object-fit: contain;
}

.lightbox__close,
.lightbox__nav {
  position: absolute;
  background: rgba(255, 255, 255, 0.1);
  border: 0;
  color: #fff;
  border-radius: 999px;
  cursor: pointer;
  line-height: 1;
}

.lightbox__close {
  top: 20px;
  right: 20px;
  width: 44px;
  height: 44px;
  font-size: 26px;
}

.lightbox__nav {
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
  font-size: 30px;
}

.lightbox__nav--prev {
  left: 16px;
}

.lightbox__nav--next {
  right: 16px;
}

.lightbox__close:hover,
.lightbox__nav:hover {
  background: rgba(255, 255, 255, 0.22);
}

/* ---------- Responsive ---------- */

@media (max-width: 1024px) {
  .steps,
  .reviews,
  .guarantees {
    grid-template-columns: repeat(2, 1fr);
  }

  .specs {
    grid-template-columns: 1fr;
    gap: 28px;
  }

  .block {
    gap: 32px;
  }
}

@media (max-width: 960px) {
  .hero__grid {
    grid-template-columns: 1fr;
    gap: 32px;
  }

  .hero {
    padding-block: 24px 40px;
  }

  .gallery__thumbs {
    gap: 8px;
  }
}

@media (max-width: 720px) {
  .trust__grid {
    grid-template-columns: 1fr 1fr;
    gap: 14px;
  }

  .trust__item {
    justify-content: flex-start;
    font-size: 0.8125rem;
  }

  .steps,
  .reviews,
  .guarantees {
    grid-template-columns: 1fr;
    gap: 24px;
  }

  .blocks {
    gap: 56px;
  }

  .block,
  .block--reverse {
    grid-template-columns: 1fr;
    gap: 20px;
  }

  .block--reverse .block__media {
    order: 0;
  }

  .gallery-grid {
    grid-template-columns: 1fr 1fr;
    gap: 10px;
  }

  .lightbox {
    padding: 60px 12px;
  }

  .lightbox__nav {
    width: 40px;
    height: 40px;
    font-size: 24px;
  }
}

/*
 * Hidden really means hidden, for the cards too.
 *
 * The browser's own rule is [hidden] { display: none }, and it lives in the user agent
 * stylesheet, which any author declaration beats. `.review { display: flex }` is an author
 * declaration, so every extra review card was painted despite carrying the hidden attribute.
 *
 * The visible symptom was the whole point of the feature disappearing: all 32 reviews rendered
 * on load, the Read more button sat under a wall it was supposed to be holding back, and
 * pressing it changed nothing anyone could see. The button had the same defect and was fixed,
 * the cards were missed.
 *
 * Anything in this theme that sets display on an element that can also be hidden needs the
 * matching [hidden] rule next to it.
 */
.review[hidden],
.reviews--more[hidden] {
  display: none;
}

/*
 * The second grid also disappears while every card inside it is still hidden.
 *
 * The list itself is never marked [hidden]. Its cards are, and they are revealed six at a
 * time. So before the first click the element was present, empty, and still carrying the
 * 24 px seam margin. That put 53 px between the last row of cards and the button, which
 * collapsed to 27 px the moment somebody clicked it. A 26 px jump, on the element the eye is
 * already resting on because it is about to be clicked.
 *
 * Written as :has rather than a class toggled from JavaScript, so it stays correct when the
 * markup renders with all cards visible for a client with no JavaScript.
 */
.reviews--more:not(:has(.review:not([hidden]))) {
  display: none;
}
