/* Shutter Scroll — v1 (clean)
   N full-width horizontal slats fill over a background as the section scrolls;
   the shutter layer climbs upward faster than the background (scroll differential).
   Pure transform, GSAP scrub, reverses on scroll-up. No WebGL, no canvas.

   Pair: shutter-scroll.js   |   Deps: gsap-core + gsap-scrolltrigger

   Modes (data-ss-mode): cover | reveal | both
   DOM:
     <section class="ss-stage"
              data-ss-mode="cover" data-ss-rows="10" data-ss-color="#1b2221"
              data-ss-line="#ffffff" data-ss-line-weight="2"
              data-ss-gain="15" data-ss-overlap="0.6" data-ss-ease="power2.out">
       <div class="ss-bg"><img src="…" alt=""></div>   background that gets covered / revealed
       <div class="ss-shutter"></div>                   slats injected by JS
     </section>
*/

.ss-stage{
  position: relative;
  width: 100%;
  height: 100vh;               /* the transition viewport — override per placement */
  overflow: hidden;
  isolation: isolate;          /* local stacking context */
  --ss-color: #1b2221;
  --ss-line: #ffffff;
  --ss-line-weight: 2px;
  --ss-gain: 15;               /* shutter climb, unitless → × 1vh below */
}

/* Background — scrolls naturally with the page. */
.ss-bg{
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
}
.ss-bg img{
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Shutter — climbs upward faster than the background.
   Over-tall by the climb distance so lifting it never opens a gap at the base. */
.ss-shutter{
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: calc(100% + (var(--ss-gain, 15) * 1vh));
  z-index: 2;
  display: flex;
  flex-direction: column;
  will-change: transform;
  transform: translateZ(0);
}

/* One slat = one row, equal division regardless of row count. Clips its own fill. */
.ss-slat{
  flex: 1 1 0;
  position: relative;
  overflow: hidden;
}

/* The fill that sweeps up through its row. */
.ss-fill{
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  background: var(--ss-color);
  will-change: transform;
  transform: translateY(100%);     /* parked below row (cover start); JS sets per mode */
}

/* Hairline riding the fill's leading edge. Opacity is animated to 0 as the slat seats,
   so the final solid state carries no seam lines. */
.ss-line{
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--ss-line-weight);
  background: var(--ss-line);
  pointer-events: none;
}

/* Reduced motion / no-JS: no shutter, background visible, content section follows in flow. */
@media (prefers-reduced-motion: reduce){
  .ss-shutter{ display: none; }
}
.ss-stage.ss-static .ss-shutter{ display: none; }
