/**
 * Promo bento (sections/promo-bento.liquid): a merchant-composed mosaic where
 * each tile carries its own span. The grid is 4 columns on desktop with
 * `grid-auto-flow: dense`, so a small tile will backfill a hole left by a
 * larger one rather than the row breaking - which is what makes an arbitrary
 * mix of sizes still read as a deliberate composition.
 *
 * Copy sits over the image in the lower-left corner, protected by a gradient
 * scrim rather than a flat overlay: a scrim keeps the top of the photograph
 * untouched while still guaranteeing contrast where the text actually is.
 */

/* Panel ground: a soft grey field behind the mosaic, inset to page-width and
   rounded - what the old `ground: panel` modifier drew. Product photography
   on this store is mostly shot on white, so on a white page the tiles lose
   their edges and the grid stops reading as a grid; the card is what gives
   each tile a boundary without having to outline every one of them.
 *
 * A scheme on this section therefore colours the CARD, not the band: the
 * frame stays unpainted (the two-token selector beats the generated
 * single-class .color-<id> rule) and .promo-bento__inner takes the scheme's
 * --color-bg. .promo-bento__head deliberately sits outside the card, as it
 * did before. __inner is a grandchild of the frame - frame >
 * .section-promo-bento.page-width > .promo-bento__inner - so this is a
 * descendant selector, not the old direct-child one. */
.promo-bento-frame[class*="color-scheme-"] {
  background-color: transparent;
  color: inherit;
}

.promo-bento-frame[class*="color-scheme-"] .promo-bento__inner {
  padding: var(--space-7);
  border-radius: calc(var(--radius-m) * 2);
  background-color: var(--color-bg);
  color: var(--color-ink);
}

@media screen and (max-width: 749px) {
  .promo-bento-frame[class*="color-scheme-"] .promo-bento__inner {
    padding: var(--space-4);
  }
}

.promo-bento__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
}

.promo-bento__heading {
  margin: 0;
}

.promo-bento__subheading {
  margin: 0;
  max-width: 60ch;
  color: var(--color-muted);
}

.promo-bento__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

/* ------------------------------------------------------------------ */
/* Tile                                                                */
/* ------------------------------------------------------------------ */
.promo-tile {
  position: relative;
  display: block;
  overflow: hidden;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-m);
  /* --color-surface, not --color-bg: a tile sits INSIDE the scheme's card, so
     reading the scheme's ground would tint it with the card's own colour.
     Surface is the scheme's "thing on top of the ground" role and is #FFFFFF
     in both scheme-1 and scheme-5, which is what a tile was before the frame
     existed. Same reason for the contain-fit media below. */
  background-color: var(--color-surface);
  text-decoration: none;
  color: inherit;
  /* Single-column default; the desktop grid overrides this per size. */
  aspect-ratio: 4 / 3;
}

.promo-tile__media {
  position: absolute;
  inset: 0;
}

.promo-tile__image,
.promo-tile__placeholder {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Product photography is shot on white and framed tightly, so filling the tile
   slices the top and bottom off the product. `contain` shows the whole thing;
   the inset keeps it off the tile's own edges so it reads as a styled shot
   rather than a raw cut-out. */
.promo-tile--fit-contain .promo-tile__image {
  object-fit: contain;
  padding: var(--space-6);
}

.promo-tile--fit-contain .promo-tile__media {
  background-color: color-mix(in srgb, var(--color-line) 26%, var(--color-surface));
}

.promo-tile__placeholder {
  background-color: var(--color-line);
  fill: var(--color-muted);
}

/* The scrim only exists on tiles that carry copy, so a pure-image mosaic stays
   exactly as bright as the photographs the merchant uploaded - and only under
   WHITE copy -
   on a light image with black text a dark scrim would fight the text instead
   of helping it. This is why the text colour is a per-tile choice: the store's
   product shots are on white, and no single scrim works for both.

   It hangs off the COPY, not off .promo-tile__media. On the media its stops
   were percentages of the TILE, and the tile's height is a merchant setting
   while the copy's height is not: three lines of copy occupy roughly a
   seventh of a `tall` tile and nearly half of a `small` one, so the same
   gradient that buried the text on a tall tile had already faded to near
   nothing where the eyebrow and title sit on a small one - which is why the
   small `keyboard` tile in particular read as copy dropped straight onto the
   photograph even though it carried the scrim all along. Anchored to the copy
   box (plus a --space-7 tail for the fade to happen in), the same percentages
   now resolve against the thing they are protecting, and every tile size gets
   identical coverage. Being a child of the copy also means a tile that hides
   its copy hides the scrim with it, with nothing to keep in step.

   z-index MUST be negative: .promo-tile__copy is a stacking context of its
   own (positioned, z-index: 1), so -1 puts the wash behind the type while the
   whole context still paints above the media - the same arrangement .btn and
   the tab pills use for their fill layers. */
.promo-tile__copy::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  top: calc(var(--space-7) * -1);
  z-index: -1;
  pointer-events: none;
}

.promo-tile--text-light .promo-tile__copy::before {
  background: linear-gradient(
    to top,
    rgb(0 0 0 / 85%) 0%,
    rgb(0 0 0 / 62%) 62%,
    rgb(0 0 0 / 0%) 100%
  );
}

/* Light images take a white wash instead, so black type has something to sit
   on without darkening the photograph. */
.promo-tile--text-dark .promo-tile__copy::before {
  background: linear-gradient(
    to top,
    rgb(255 255 255 / 94%) 0%,
    rgb(255 255 255 / 74%) 62%,
    rgb(255 255 255 / 0%) 100%
  );
}

.promo-tile__copy {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  /* Above the media AND its scrim - without this the copy's paint order
     depends on DOM order alone, which is fragile the moment anything else is
     added to the tile. */
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-5);
}

.promo-tile--text-light .promo-tile__copy {
  color: #fff;
}

.promo-tile--text-dark .promo-tile__copy {
  color: var(--color-ink);
}

/* Inherits the tile's text colour rather than using --color-accent: the accent
   is cyan, which was both off-brand here and low-contrast on pale product
   shots. Opacity does the hierarchy instead. */
.promo-tile__eyebrow {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.78;
}

.promo-tile__title {
  font-family: var(--font-heading);
  font-size: clamp(20px, 2.2vw, 30px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.promo-tile__subtitle {
  font-size: 13px;
  line-height: 1.45;
  opacity: 0.82;
}

/* Hover belongs to linked tiles only - a plain image tile isn't clickable and
   shouldn't pretend otherwise. */
/* The tile frames a photograph, so its edge goes to ink rather than purple -
   the same move every other bordered box on the site now makes, and one that
   does not tint the image it is framing. */
a.promo-tile:hover {
  border-color: var(--color-ink);
}

a.promo-tile:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: no-preference) {
  .promo-tile__image {
    transition: transform 500ms cubic-bezier(0.16, 1, 0.3, 1);
  }

  a.promo-tile:hover .promo-tile__image,
  a.promo-tile:focus-visible .promo-tile__image {
    transform: scale(1.04);
  }

  .promo-tile {
    transition: border-color 200ms ease;
  }
}

/* ------------------------------------------------------------------ */
/* Tablet: 2 columns - wide/large go full width, tall keeps its height  */
/* ------------------------------------------------------------------ */
@media screen and (min-width: 750px) {
  .promo-bento__grid {
    grid-template-columns: repeat(2, 1fr);
    grid-auto-rows: 260px;
    grid-auto-flow: dense;
  }

  .promo-tile {
    aspect-ratio: auto;
    grid-column: span 1;
    grid-row: span 1;
  }

  .promo-tile--wide,
  .promo-tile--large {
    grid-column: span 2;
  }

  .promo-tile--tall,
  .promo-tile--large {
    grid-row: span 2;
  }
}

/* ------------------------------------------------------------------ */
/* Desktop: the real 4-column mosaic                                    */
/* ------------------------------------------------------------------ */
@media screen and (min-width: 990px) {
  .promo-bento__grid {
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 300px;
  }

  .promo-tile--wide {
    grid-column: span 2;
    grid-row: span 1;
  }

  .promo-tile--tall {
    grid-column: span 1;
    grid-row: span 2;
  }

  .promo-tile--large {
    grid-column: span 2;
    grid-row: span 2;
  }
}

/* Hover reveal (section setting "Tile text: On hover").

   Opacity and a small lift, never `display` or `visibility`: the copy stays
   in the accessibility tree and in the document, so a screen reader still
   announces what the tile links to when the pointer has never been near it.

   The scrim comes with it for free - it is `.promo-tile__copy::before`, a
   child of the box being faded, so there is no second rule to keep in step
   and no window where a wash sits on the photograph with no text on it.

   `:focus-within` is what makes this reachable by keyboard. A linked tile is
   an <a>, so tabbing to it reveals the copy exactly as hovering does; an
   unlinked tile has nothing focusable inside it, but it is also not in the
   tab order at all, so there is no state where a keyboard user can land on a
   tile and not see its text. */
.promo-tile--reveal-hover .promo-tile__copy {
  opacity: 0;
  transform: translateY(var(--space-2));
}

.promo-tile--reveal-hover:hover .promo-tile__copy,
.promo-tile--reveal-hover:focus-within .promo-tile__copy {
  opacity: 1;
  transform: none;
}

/* Touch has no hover, and `@media (hover: none)` is the only thing that
   separates a phone from a laptop with a touchscreen. Without this the copy
   would be permanently invisible on a phone - the tap that would reveal it is
   the same tap that follows the link. */
@media (hover: none) {
  .promo-tile--reveal-hover .promo-tile__copy {
    opacity: 1;
    transform: none;
  }
}

@media screen and (prefers-reduced-motion: no-preference) {
  .promo-tile--reveal-hover .promo-tile__copy {
    transition: opacity 240ms ease, transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
  }
}

/* A tile video fills its tile the way the image does, over the still, and
   shows once it is actually playing (assets/ui-upgrades.js adds
   .is-playing) - a clip that has not started never covers the tile with a
   blank frame. */
.promo-tile__video {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.3s ease, transform 500ms cubic-bezier(0.16, 1, 0.3, 1);
}

.promo-tile__video.is-playing {
  opacity: 1;
}
