/**
 * Image with text.
 *
 * Mobile-first single column, becoming a 60/40 split at 990px with the
 * media column always taking the wide track (the reference-theme look). The side
 * setting is applied with `order` at that same breakpoint and nowhere else,
 * so on mobile the image is always first regardless of what the merchant
 * chose - a side preference has no meaning in one column.
 *
 * The two fit modes are genuinely different layouts, not one property swap:
 *   cover    fills a fixed 4:3 frame and crops (lifestyle photography)
 *   contain  keeps its own aspect ratio and is capped by height, so a
 *            product shot on white is never sliced through
 * `contain` therefore has no fixed frame at all - forcing one would put the
 * product in a letterbox, which is the thing the option exists to avoid.
 */
.section-image-with-text {
  padding-block: var(--space-9);
}

.image-with-text__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: center;
}

.image-with-text__media {
  border-radius: var(--radius-m);
  overflow: hidden;
}

/* The tinted panel exists for product shots on solid white, which otherwise
   dissolve into the page with no edge to sit against. Same role as
   promo-bento's grey ground. */
.image-with-text__media--panel {
  background-color: color-mix(in srgb, var(--color-line) 45%, var(--color-bg));
}

.image-with-text__media--fit-cover .image-with-text__image {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.image-with-text__media--fit-contain .image-with-text__image {
  width: 100%;
  height: auto;
  max-height: 520px;
  object-fit: contain;
}

.image-with-text__media--fit-contain.image-with-text__media--panel {
  padding: var(--space-5);
}

.image-with-text__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-5);
}

.image-with-text__heading {
  margin: 0;
}

.image-with-text__body {
  width: 100%;
}

/* With only one of the two halves present the grid would still reserve a
   second column's worth of gap; collapsing to a single measured column keeps
   it reading as a deliberate block rather than a half-empty row. */
.image-with-text__grid--copy-only .image-with-text__copy {
  max-width: 68ch;
}

@media screen and (min-width: 990px) {
  .section-image-with-text {
    padding-block: var(--space-10);
  }

  /* The reference theme's split: the image column dominates (~60/40) and
     the copy sits centred beside it, which reads as a scene with a caption
     rather than two equal cards. The wider track always belongs to the
     media column - order swaps which column that is. */
  .image-with-text__grid {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: var(--space-8);
  }

  .image-with-text__grid--media-right {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
  }

  .image-with-text__grid--media-only,
  .image-with-text__grid--copy-only {
    grid-template-columns: 1fr;
  }

  /* Cover mode grows into a cinematic frame on wide screens instead of a
     squat 4:3 card - the reference's fixed-height banner look. Contain mode
     is untouched: its whole point is never cropping a product shot. */
  .image-with-text__media--fit-cover .image-with-text__image {
    aspect-ratio: auto;
    height: clamp(360px, 42vw, 560px);
  }

  /* Explicit on both children rather than only the one being moved: leaving
     the copy at its default `order: 0` works today but breaks the moment
     another child (a caption, a badge) is added between them. */
  .image-with-text__grid--media-right .image-with-text__media {
    order: 2;
  }

  .image-with-text__grid--media-right .image-with-text__copy {
    order: 1;
  }
}

/* ------------------------------------------------------------------ */
/* Placeholder: no image chosen yet                                    */
/* ------------------------------------------------------------------ */
/* Shopify's placeholder SVGs carry no intrinsic size, so the column needs a
   ratio of its own or it collapses to zero height - which would defeat the
   point of showing a placeholder at all. */
.image-with-text__media--placeholder {
  aspect-ratio: 4 / 3;
  background-color: color-mix(in srgb, var(--color-line) 40%, var(--color-bg));
  border-radius: var(--radius-m);
  overflow: hidden;
}

.image-with-text__placeholder {
  width: 100%;
  height: 100%;
  fill: var(--color-muted);
  opacity: 0.5;
}

/* ------------------------------------------------------------------ */
/* Copy reveal: heading, then body, then button                        */
/* ------------------------------------------------------------------ */
/* The global [data-reveal] treatment (base.css) brings a whole element in as
   one unit in 500ms. For a headline, a paragraph and a button that is too
   quick and too flat - all three land at once, so the eye has nothing to
   follow and the section just appears.

   The stagger is driven off the WRAPPER's .is-revealed rather than by giving
   each child its own [data-reveal]. Three observers would fire at three
   different scroll positions, so the order would depend on where the reader
   stopped scrolling - sometimes sequential, sometimes simultaneous, sometimes
   backwards. One trigger and CSS delays make the sequence the same every
   time.

   The wrapper therefore carries the trigger but not the motion: it is pinned
   visible so its fade does not compound with its children's. Everything stays
   inside html.js, so with no JavaScript all of it is simply visible. */
html.js .image-with-text__copy[data-reveal] {
  opacity: 1;
  transform: none;
}

html.js .image-with-text__copy[data-reveal] > * {
  opacity: 0;
  transform: translateY(18px);
}

html.js .image-with-text__copy[data-reveal].is-revealed > * {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: no-preference) {
  html.js .image-with-text__copy[data-reveal] > * {
    transition: opacity 900ms ease-out, transform 900ms cubic-bezier(0.16, 1, 0.3, 1);
  }

  /* Nth-child rather than a delay per named class: the three children are
     each optional, so the heading is not always first in the DOM. Positional
     delays keep the rhythm right whichever combination the merchant fills
     in. */
  html.js .image-with-text__copy[data-reveal] > *:nth-child(2) {
    transition-delay: 140ms;
  }

  html.js .image-with-text__copy[data-reveal] > *:nth-child(3) {
    transition-delay: 280ms;
  }
}
