/* ==========================================================================
   TUOIL — product list
   Four full-bleed tiles, two by two: photo under a neutral veil, a centred
   label that opens into a description. On hover, after ventos.com, the photo
   slides and the tile lights up in its category's gradient.
   ========================================================================== */

.s-plist {
  background: var(--c-base-deep);
}

/* --- Grid ------------------------------------------------------------------- */
.s-plist__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  /* edge to edge, no gaps and no outer margin: the tiles are the section */
  gap: 0;
}

.s-plist__tile {
  /* hover: 50px of travel on its own 0.7s ease */
  --plist-slide: 50px;
  --plist-dur: 700ms;
  --plist-ease: cubic-bezier(0.45, 0, 0.3, 1);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 20 / 7;
  overflow: hidden;
  background: #0E1206;
  color: var(--c-on-dark);
  text-decoration: none;
}

/* --- Tile media ---------------------------------------------------------------
   Three nested layers, one transform each: parallax on the outer, the reveal
   scale in the middle, the hover scale on the image. They never fight over
   the same property, so GSAP and CSS can each own their own layer.
   -------------------------------------------------------------------------- */
.s-plist__media {
  position: absolute;
  inset: 0;
  overflow: hidden;
  /* its own stack, so the shade can sit over the glow without rising above
     the type */
  isolation: isolate;
}

.s-plist__parallax {
  position: absolute;
  inset: -7% 0;
  will-change: transform;
}

.s-plist__reveal {
  width: 100%;
  height: 100%;
}

/* The hover follows ventos.com: the photograph is 50px wider than its tile and
   parked 50px to the left, and slides home when the pointer arrives. */
.s-plist__img {
  width: calc(100% + var(--plist-slide));
  max-width: none;
  height: 100%;
  object-fit: cover;
  transform: translate3d(calc(-1 * var(--plist-slide)), 0, 0);
  transition: transform var(--plist-dur) var(--plist-ease);
}

/* At rest the photograph keeps its own colours under a flat neutral veil --
   no category tint -- which is what gives the grid its quiet
   grey-washed look. The veil thins a little on hover. */
.s-plist__tint {
  position: absolute;
  inset: 0;
  background: rgba(115, 115, 115, 0.5);
  transition: opacity 400ms linear;
}

/* A soft pool of shade under the type. It is what guarantees the label its
   contrast: the photograph behind can be anything, including white powder or
   sky, and the reading stays above 4.5:1 through the veil and the glow. */
.s-plist__scrim {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 78% 70% at 50% 50%,
    rgba(10, 12, 8, 0.44) 0%,
    rgba(10, 12, 8, 0.26) 55%,
    rgba(10, 12, 8, 0.06) 100%);
  z-index: 1; /* over the glow as well as the photograph */
}

/* Two of the gradients, the yellow and the green, are too light
   to carry white type on their own. Their tiles set --glow-shade, and this
   extra pool of shade comes up under the type with the glow -- only there,
   so the corners keep the colour at full strength. */
.s-plist__scrim::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 66% 60% at 50% 50%,
    rgba(10, 12, 8, var(--glow-shade, 0)) 0%,
    rgba(10, 12, 8, calc(var(--glow-shade, 0) * 0.55)) 55%,
    rgba(10, 12, 8, 0) 100%);
  opacity: 0;
  transition: opacity 600ms linear;
}

/* The tile's glow: a saturated gradient at 45deg, deep at the lower left and
   bright at the upper right, fading in over the photograph on hover. The two
   stops keep 0.9 / 0.7 opacities so the picture still shows
   through at the bright corner. */
.s-plist__wash {
  position: absolute;
  inset: 0;
  background: linear-gradient(45deg,
    color-mix(in srgb, var(--glow-a) 90%, transparent) 0%,
    color-mix(in srgb, var(--glow-b) 70%, transparent) 100%);
  opacity: 0;
  transition: opacity 600ms linear;
}

/* --- Tile body ------------------------------------------------------------------ */
.s-plist__body {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  padding: var(--sp-4);
  text-align: center;
}

.s-plist__label {
  font-family: var(--font-display);
  font-size: clamp(1.125rem, 0.7rem + 1.3vw, 1.75rem);
  font-weight: var(--fw-medium);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-right: -0.1em;
  /* rises 15px on hover, on the photograph's own curve */
  transform: translateY(15px);
  transition: transform var(--plist-dur) var(--plist-ease);
}

.s-plist__rule {
  width: 72px;
  height: 1px;
  margin-top: var(--sp-2);
  background: currentColor;
  transform: scaleX(0) translateY(14px);
  transform-origin: left center;
  transition: transform var(--dur-slow) var(--ease-out);
}

.s-plist__desc {
  max-width: 46ch;
  margin-top: var(--sp-2);
  font-size: var(--fs-small);
  color: rgba(255, 255, 255, 0.92);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
}

.s-plist__tile:hover .s-plist__img,
.s-plist__tile:focus-visible .s-plist__img { transform: translate3d(0, 0, 0); }

.s-plist__tile:hover .s-plist__tint,
.s-plist__tile:focus-visible .s-plist__tint { opacity: 0.8; }

.s-plist__tile:hover .s-plist__wash,
.s-plist__tile:focus-visible .s-plist__wash,
.s-plist__tile:hover .s-plist__scrim::after,
.s-plist__tile:focus-visible .s-plist__scrim::after { opacity: 0.8; }

.s-plist__tile:hover .s-plist__label,
.s-plist__tile:focus-visible .s-plist__label { transform: translateY(0); }

.s-plist__tile:hover .s-plist__rule,
.s-plist__tile:focus-visible .s-plist__rule { transform: scaleX(1) translateY(0); }

.s-plist__tile:hover .s-plist__desc,
.s-plist__tile:focus-visible .s-plist__desc {
  opacity: 1;
  transform: translateY(0);
  transition-delay: 90ms;
}

.s-plist__tile:focus-visible {
  outline: 2px solid var(--c-on-dark);
  outline-offset: -6px;
}

/* --- Tints ---------------------------------------------------------------------- */
.s-plist__tile--oils { --glow-a: var(--c-oils-glow-a); --glow-b: var(--c-oils-glow-b); }
.s-plist__tile--hydro { --glow-a: var(--c-hydro-glow-a); --glow-b: var(--c-hydro-glow-b); }
.s-plist__tile--licorice { --glow-a: var(--c-licorice-glow-a); --glow-b: var(--c-licorice-glow-b); --glow-shade: 0.5; }
.s-plist__tile--herbs { --glow-a: var(--c-herbs-glow-a); --glow-b: var(--c-herbs-glow-b); --glow-shade: 0.5; }

/* --- Reveal --------------------------------------------------------------------
   Start state only applies once script is running; without it the tiles are
   simply there. */
.js .s-plist__tile[data-animate] {
  opacity: 0;
  transform: translateY(24px);
}

/* --- Adaptive -------------------------------------------------------------------- */
@media (max-width: 768px) {
  .s-plist__grid { grid-template-columns: 1fr; }
  .s-plist__tile { aspect-ratio: 16 / 9; }

  /* Label, rule and description stand as one taller block here, so the
     shade under them has to reach further down the tile. */
  .s-plist__scrim {
    background: radial-gradient(ellipse 110% 90% at 50% 50%,
      rgba(10, 12, 8, 0.56) 0%,
      rgba(10, 12, 8, 0.40) 55%,
      rgba(10, 12, 8, 0.14) 100%);
  }

  /* No hover on a phone: the description is simply part of the tile. */
  .s-plist__label { transform: none; }
  .s-plist__rule { transform: scaleX(1); }
  .s-plist__desc { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .s-plist__parallax { transform: none !important; }
}
