/* ============================================================
   TCA WEBSITE — "PROGRAMS" ZOOM SCENE
   Same sticky-frame scroll-depth technique as hero.css /
   about-scene.css, but instead of layers translating at different
   speeds, 3 stacked layers (back path/grass -> mid building -> front
   framing trees) each scale up around the SAME focal point (the
   school building, ~58%/42%) at DIFFERENT rates as you scroll — a
   multi-plane dolly-zoom instead of one flat image getting bigger.
   The front trees scale fastest (they're "closest to the lens," so
   they should rush past quickest), the back layer scales least. See
   parallax.js initZoomScene for the per-layer scale ranges.

   Because progress is scroll-position-linked both ways, scrolling
   back up plays the zoom in reverse — the "zoom in/out" is inherent
   to how this already works, not a separate effect to build.

   This is a SHORT scene on purpose: it's the transition beat between
   about-scene and the flat white catalog below, not a full illustrated
   world like hero/about — see the note on .programs-scene-content for
   why the dense card grid stays in the flat section instead of living
   on top of this moving background.
   ============================================================ */

.programs-scene {
  position: relative;
  background: var(--navy-dark);
  padding: 0;
}

.programs-scene-wrapper {
  position: relative;
  height: 170vh;
}

.programs-scene-frame {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  display: flex;
  align-items: center;
  /* JS writes the live scroll progress (0–1) here every tick; the
     vignette below reads it directly in a calc(), so there's only
     one per-frame style write instead of two. */
  --progress: 0;
}

.programs-scene-media {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.programs-scene-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 58% 42%;
  display: block;
  transform: scale(1);
  transform-origin: 58% 42%; /* the school building — same focal point for
                                 all 3 layers so they zoom toward one point
                                 in space rather than drifting apart */
  will-change: transform;
}

/* Stacking order back -> front, matching the art's own depth. The mid
   and front layers are transparent everywhere except the building/
   trees, so the back layer shows through around them at scale 1 and
   gets progressively covered as the front layers scale up faster. */
.programs-scene-media--back  { z-index: 1; }
.programs-scene-media--mid   { z-index: 2; }
.programs-scene-media--front { z-index: 3; }

/* ---- Text-legibility scrim — same gradient shape as hero's, so a
   dark-panel-behind-text treatment is consistent across every scene
   on the page rather than invented fresh per section. Sits above the
   vignette (z-index 2) but below the top/bottom fades' z-index isn't
   relevant since they occupy different screen regions. */
.programs-scene-scrim {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background: linear-gradient(100deg,
    rgba(6, 5, 20, 0.88) 0%,
    rgba(6, 5, 20, 0.7) 30%,
    rgba(6, 5, 20, 0.28) 54%,
    transparent 80%);
}

/* ---- Vignette that deepens as you zoom — the actual "moving through 3D
   space" cue. A flat image scale alone reads as "photo getting bigger";
   darkened, closing-in edges are what sell depth/motion on top of that,
   the same trick a dolly-zoom or a camera push-in uses. */
.programs-scene-vignette {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background: radial-gradient(ellipse at 58% 42%,
    transparent 35%,
    rgba(0, 8, 20, 0.65) 100%);
  opacity: calc(0.35 + (var(--progress) * 0.5));
}

/* ---- Top fade — converges to the exact color/opacity hero's bottom
   and about-scene's top already meet at, so this scene's handoff from
   about-scene reads as the same seam treatment established there,
   not a one-off. See about-scene.css .about-scene-top-fade for the
   matching value on the other side of this boundary. */
.programs-scene-top-fade {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 24%;
  z-index: 5;
  pointer-events: none;
  background: linear-gradient(to bottom,
    rgba(6, 5, 20, 0.94) 0%,
    rgba(6, 5, 20, 0.5) 16%,
    transparent 36%);
}

/* ---- Bottom fade to white — this is the easy handoff. A painted/photo
   scene fading to a solid flat color always works cleanly (there's no
   competing content to mismatch, just a curtain), unlike the scene-to-
   scene seams above — which is why this one didn't need the same
   diagnostic treatment. */
.programs-scene-fade {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 32%;
  z-index: 5;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent 0%, var(--white) 92%);
}

/* ---- Content overlay ---- */
.programs-scene__content {
  position: relative;
  z-index: 6;
  max-width: 650px;
  padding: 0 3rem;
  margin-top: -6vh;
}

.programs-scene__content .section-label,
.programs-scene__content .section-title,
.programs-scene__content .section-text {
  margin-bottom: 1rem;
}

.programs-scene__content .section-text {
  color: rgba(255, 255, 255, 0.85);
}

.programs-scene__content .section-link {
  color: var(--gold-light);
}

@media (max-width: 900px) {
  .programs-scene-wrapper { height: 145vh; }
  .programs-scene__content {
    padding: 0 1.5rem;
    max-width: 100%;
  }
  .programs-scene-scrim {
    background: linear-gradient(180deg,
      rgba(6, 5, 20, 0.82) 0%,
      rgba(6, 5, 20, 0.86) 30%,
      rgba(6, 5, 20, 0.9) 100%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .programs-scene-wrapper { height: auto; }
  .programs-scene-frame { position: relative; }
  .programs-scene-media img { transform: scale(1) !important; }
  .programs-scene-vignette { opacity: 0.35 !important; }
}
