/* ============================================================
   SILICA WORKS - showcase
   ------------------------------------------------------------
   Three plates under the testimonial deck. Same paper ground and
   ink type as the rest of the page; the only new idea here is the
   row itself - three equal columns, each one an image with its
   title and a line of copy sitting under it.

   The middle plate is dropped slightly below its neighbours so the
   row reads as a hand of three rather than a filmstrip. That
   offset is the whole composition, so it is the first thing to
   change if the row ever needs to sit flat.

   Reveal is driven by js/showcase.js; this file owns the resting
   look and the pre-reveal state the script animates out of.

   Below 1000px there is no room for three across, so the row
   becomes a single column and the middle plate's offset is
   dropped with it.
   ============================================================ */

.sw-showcase {
  /* Relative and opaque on purpose, and both matter beyond this
     section. The testimonial deck above releases its vertical clip
     (overflow-y: visible) so its cards can fly in from below the
     section edge - during that travel they pass through the space
     this section occupies. Being positioned and later in document
     order, this paints over them, so the cards stay hidden until
     they rise into their own section.
     Do not make this static or transparent without giving the deck
     another way to mask its intro. */
  position: relative;
  width: 100%;
  /* The section is a plain block, not the centred flex column
     .sw-section gives it: the head and the row stack from the top
     with their own spacing, and centring them would leave the row
     floating in a tall section. */
  display: block;
  background: var(--sw-paper);
  overflow: hidden;

  /* ----------------------------------------------------------
     Last section on the page, so this one hands over to the
     footer parallax - and it has to end close to its content to
     do that.

     .page carries a mask that fades its final 16rem to
     transparent, letting the sticky footer bleed up through the
     white (css/footer.css). That ramp is meant to land on real
     content. .sw-section's own sizing puts empty space there
     instead: min-height: 100vh centres a short section in a full
     viewport, and padding-bottom: 10rem clears the fixed nav for
     sections that are scrolled THROUGH. Neither applies to the
     last one - together they left a band of blank white under the
     plates, which is what the mask was dissolving.

     So: no min-height, and the bottom padding is cut to the mask
     ramp's own length. That 16rem is not empty space held open -
     it IS the dissolve, the stretch where the green comes up
     through the white. Setting it to 0 does not close a gap; it
     pulls the captions into the transparent end of the ramp and
     fades the copy itself.
     ---------------------------------------------------------- */
  min-height: 0;
  /* Exactly the ramp length, so the fade begins below the last row
     of captions rather than across it. */
  padding-bottom: 16rem;
}

/* ------------------------------------------------------------
   Heading
   ------------------------------------------------------------
   Identical face and hooks to the testimonial heading above it -
   .sw-featured-title carries the type, data-featured-title and
   data-featured-slide carry the slide, and data-ft-slide carries
   the velocity lean. Nothing typographic is set here, so the two
   headings cannot drift apart.
   ------------------------------------------------------------ */
.sw-sc-head {
  /* Plain block, and nothing here narrows it. .sw-featured-title is
     a flex row with space-between - it spreads its three words
     across whatever width it is given, so the head must hand it the
     full measure. Centring the head (align-items: center, or the
     width: max-content the testimonial head uses) would shrink-wrap
     it to its content instead, bunching the words together and
     losing the edge-to-edge spread the featured heading has. That
     spread IS the treatment, so it is inherited rather than
     re-specified. */
  display: block;
  /* The pill hangs off the foot of the middle word and is
     absolutely placed, so it takes no space of its own - this
     clearance is what keeps it off the first row of plates. */
  margin-bottom: clamp(6rem, 12vh, 10rem);
}

/* ------------------------------------------------------------
   The row
   ------------------------------------------------------------ */
.sw-sc-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Wide enough that the three plates read as separate pieces
     rather than as one contact sheet. */
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: start;
}

.sw-sc-item {
  display: flex;
  flex-direction: column;
  /* Pre-reveal state. js/showcase.js clears both; if the script
     never runs the :not() guard at the foot of this file leaves
     the plates visible rather than blank. */
  opacity: 0;
  transform: translateY(2.5rem);
  will-change: transform, opacity;
}

/* The middle plate rides low, so the row reads as dealt rather
   than ruled. Kept off the reveal transform - that one is written
   inline by GSAP and would overwrite this. */
.sw-sc-item--drop {
  margin-top: clamp(2rem, 6vh, 5rem);
}

/* ------------------------------------------------------------
   Plate
   ------------------------------------------------------------
   The frame owns the crop and the corner; the image fills it and
   scales inside it on hover. Two elements, so the scale never
   fights the frame's own corner.
   ------------------------------------------------------------ */
.sw-sc-frame {
  position: relative;
  width: 100%;
  /* Portrait. The three source images are different shapes, so the
     ratio is set here and the crop is left to object-fit - that way
     swapping an image never changes the row's rhythm. */
  aspect-ratio: 4 / 4.4;
  overflow: hidden;
  /* Bevelled, not rounded, to match the rest of the page - the nav
     bar (--sw-notch, js/menu.js) and the showreel plate
     (.sw-reveal-frame in css/intro.css) cut every corner at 45
     degrees off the same 14px. These plates carried a 0.75rem
     radius and were the only images on the page not doing it.

     Eight points rather than the two-corner cut the tags and
     buttons use: that shape is for small chips, where a full bevel
     would eat the whole corner. On a plate this size all four
     corners read, which is what matches the showreel above. */
  --sw-plate-notch: 14px;
  clip-path: polygon(
    var(--sw-plate-notch) 0,
    calc(100% - var(--sw-plate-notch)) 0,
    100% var(--sw-plate-notch),
    100% calc(100% - var(--sw-plate-notch)),
    calc(100% - var(--sw-plate-notch)) 100%,
    var(--sw-plate-notch) 100%,
    0 calc(100% - var(--sw-plate-notch)),
    0 var(--sw-plate-notch)
  );
  /* Paper, not white: an image that happens to have a white edge
     still reads as a plate against this while it loads. */
  background: var(--sw-paper, #f4f4f2);

  /* Seats the plate on the paper instead of leaving it pasted flat.

     drop-shadow, not box-shadow: box-shadow is drawn from the
     element's rectangular border box, so it would ignore the
     clip-path above and leave four square shadow corners jutting
     out past the bevel. A filter shadow is taken from the CLIPPED
     silhouette, so it follows all eight sides. Same reasoning as
     the tags in css/tags.css.

     Two layers rather than one: a short, tighter shadow for the
     contact edge where the plate meets the paper, and a wide, soft
     one for the ambient cast. A single shadow has to choose
     between the two and reads as a blur either way. Both are the
     ink colour at low alpha rather than black - a neutral grey
     cast on this warm paper looks like dirt. */
  filter:
    drop-shadow(0 2px 3px rgba(20, 20, 15, 0.1))
    drop-shadow(0 18px 28px rgba(20, 20, 15, 0.14));
}

.sw-sc-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transform: scale(1.02);
  transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}

.sw-sc-item:hover .sw-sc-frame img {
  transform: scale(1.06);
}

/* ------------------------------------------------------------
   Caption
   ------------------------------------------------------------ */
.sw-sc-body {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding-top: 1.4rem;
}

.sw-sc-title {
  /* Named rather than left to font-weight: the Söhne faces are
     declared as separate families in styles.css, so a weight alone
     would leave this on Inter Tight with a synthesized bold. Same
     reasoning as .sw-featured-title. */
  font-family: "sohne-bold", "Inter Tight", sans-serif;
  font-weight: 700;
  font-size: clamp(1.15rem, 1.6vw, 1.5rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: #14140f;
}

.sw-sc-desc {
  font-size: clamp(0.95rem, 1.05vw, 1.05rem);
  line-height: 1.5;
  color: #56564f;
  /* Held short so the three descriptions stay one block of copy
     each rather than running to four or five ragged lines. */
  max-width: 34ch;
}

/* ------------------------------------------------------------
   No-JS / reduced motion fallback
   ------------------------------------------------------------
   js/showcase.js marks the section once it has taken the plates
   over. Until then - and forever, if the script never runs - the
   plates sit at their resting state rather than at opacity 0.
   ------------------------------------------------------------ */
.sw-showcase:not([data-showcase-ready]) .sw-sc-item {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .sw-sc-item {
    opacity: 1;
    transform: none;
  }

  .sw-sc-frame img,
  .sw-sc-item:hover .sw-sc-frame img {
    transform: none;
    transition: none;
  }
}

/* ------------------------------------------------------------
   Narrow
   ------------------------------------------------------------ */
@media (max-width: 1000px) {
  /* .sw-section's narrow rule re-declares padding with the
     SHORTHAND (4rem 1.5rem 8rem in css/styles.css), which wins over
     the padding-bottom set above - same specificity, later in the
     cascade - and would pull the captions into the faded end of
     the mask. Restated here so the ramp still starts below them. */
  .sw-showcase {
    padding-bottom: 16rem;
  }

  .sw-sc-head {
    /* .sw-featured-title stacks to three left-aligned lines below
       1000px on its own; the head only tightens the gap under it. */
    margin-bottom: clamp(4rem, 9vh, 7rem);
  }

  .sw-sc-row {
    grid-template-columns: 1fr;
    gap: 3.5rem;
  }

  /* One column: nothing to fan against, so the drop is dead space. */
  .sw-sc-item--drop {
    margin-top: 0;
  }

  .sw-sc-frame {
    aspect-ratio: 3 / 4;
    /* The nav steps its own bevel to 11px at this width
       (css/menu.css), so the plates follow it down - the two shapes
       are meant to read as the same cut at every size. */
    --sw-plate-notch: 11px;
    /* Pulled in with the bevel. One column means a near full-width
       plate, and the desktop cast under one of those reads as a
       heavy band across the page rather than as depth. */
    filter:
      drop-shadow(0 2px 3px rgba(20, 20, 15, 0.09))
      drop-shadow(0 10px 18px rgba(20, 20, 15, 0.12));
  }

  .sw-sc-desc {
    max-width: 46ch;
  }
}
