/* ════════════════════════════════════════════════════════════
   3D Z-CORRIDOR — services section
   Ported from the painting site's ServicesScene (Scenes.tsx).

   The six service cards stop being a grid of tiles and become objects
   flying toward you through Z-space: one sticky 100svh stage, a
   perspective box, one panel per card, all driven by a single
   ScrollTrigger in js/corridor.js.

   This file only styles the shell. Every per-frame value (panel
   transform / opacity / filter / z-index, backdrop and heading opacity)
   is written by js/corridor.js — see the formulas there.

   Revert = remove this <link> and the corridor <script>. The markup is
   untouched in index.html; the JS builds the structure at runtime and
   bails out entirely on phones, without GSAP, or under
   prefers-reduced-motion — in which case NONE of these rules match and
   the normal .services-grid renders as before.
   ════════════════════════════════════════════════════════════ */

/* ── OUTER: the scroll runway ──────────────────────────────────
   Height and the negative top margin (the overlap with the section
   above) are both set in JS, because both depend on the viewport
   height and on how tall the preceding block actually is. */
.eh-corridor {
  position: relative;
  z-index: 25;          /* above the stat ticker (z1) and the bone sections (z2) */
  width: 100%;
  pointer-events: none; /* re-enabled on the centred panel only, in JS */
}

/* ── STAGE: what you actually look at ─────────────────────────
   CSS sticky, NOT a ScrollTrigger pin. A pin injects a spacer
   element, and a spacer cannot be overlapped by a negative margin —
   which is exactly how this scene fades in over the block above it
   and gets covered by the one below. */
.eh-corridor__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  width: 100%;
  overflow: hidden;
  pointer-events: none;
}

/* ── BACKDROP ──────────────────────────────────────────────────
   Dark, not bone. The page is bone (#F5F1EA) here, so a bone corridor
   would show white photo panels against a near-white void — no edge,
   no sense of depth, and the distance blur would be invisible. Against
   --near-black the panels read as lit objects moving through space,
   which is the whole point of the scene. The site already uses
   --near-black for full-bleed sections (stat ticker, dark sections),
   so this is on-palette rather than a one-off.
   Slight radial lift in the middle so the far panels have something to
   recede into instead of flat black. Starts at opacity 0; JS fades it. */
.eh-corridor__bg {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 90% at 50% 42%, #26261F 0%, #1C1C19 58%, #121210 100%);
  opacity: 0;
}

/* ── HEADING ───────────────────────────────────────────────────
   The section's own .section-header, moved in here by JS. The wrapper
   owns the animated transform/opacity so the header's own inline
   styles (set by the site's other scripts) are never fought over. */
.eh-corridor__head {
  position: absolute;
  left: 50%;
  top: 0;
  z-index: 300;
  /* The source pins this block at top:7rem and centres it in 90vw/36rem.
     Same result here (7rem of padding-top, text held to 36rem by the
     rule below) but the ELEMENT is full-bleed, because it has to carry a
     scrim: the heading floats over the corridor at z-index 300 and a
     panel approaching the camera scales up past it — measured, a 48rem
     panel at translateZ +430px is 1104px wide and fills the stage — so
     the heading is regularly sitting on top of a photo.
     A full-width top gradient is the only scrim with no visible edge:
     boxed radial vignettes cut off against the panel (tried, it drew a
     line across the photo). Alpha stays >= 0.8 everywhere the text sits,
     which is bone-on-scrim ~9:1 over even a pure-white photo, and fades
     to nothing well below the copy. */
  width: 100vw;
  max-width: none;
  padding: 7rem 1.5rem 8rem;
  text-align: center;
  background: linear-gradient(to bottom,
    rgba(18, 18, 16, 0.94) 0%,
    rgba(18, 18, 16, 0.90) 55%,
    rgba(18, 18, 16, 0.80) 72%,
    rgba(18, 18, 16, 0.35) 88%,
    rgba(18, 18, 16, 0) 100%);
  transform: translate(-50%, 0);
  opacity: 0;
  pointer-events: none;
}
.eh-corridor__head .section-header {
  margin-bottom: 0;
  width: 90vw;
  max-width: 36rem;   /* the source's text measure */
  margin-left: auto;
  margin-right: auto;
}

/* On the dark backdrop the header has to be inverted. Contrast against
   the darkest part of the backdrop (#121210):
     bone  #F5F1EA  → 15.2:1   (AA needs 4.5)
     copy  rgba(245,241,234,.78) → ~9:1
     eyebrow #D8E6BE → 12.9:1  (olive-light, keeps the brand accent) */
.eh-corridor__head h2 {
  color: var(--bone);
  /* animations.css starts every .section-header h2 at opacity 0 and waits
     for an IntersectionObserver to add .h2-visible. In here the wrapper
     already controls the fade, so pin the h2 visible and drop its
     transition — otherwise it can sit invisible inside a visible header. */
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}
.eh-corridor__head p { color: rgba(245, 241, 234, 0.78); }
.eh-corridor__head .eyebrow { color: #D8E6BE; }

/* ── 3D BOX ────────────────────────────────────────────────────
   One perspective for the whole stage, so all six panels share a
   vanishing point and read as one corridor. */
.eh-corridor__box {
  position: absolute;
  inset: 0;
  perspective: 1400px;
}

/* ── PANELS ────────────────────────────────────────────────────
   JS writes transform (translateZ), opacity, filter and z-index every
   frame; nothing here may animate, or it would fight the scrub. */
.eh-corridor__panel {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 80vw;
  max-width: 48rem;
  will-change: transform;
  transform: translate(-50%, -50%);
  opacity: 0;
  pointer-events: none;
}

/* The framed media box the source uses: fixed aspect, clipped, soft
   border and a deep drop shadow so the panel has an edge against the
   dark. 3/4 on narrow viewports, 16/10 from 640px (the corridor itself
   never runs below 768px, so 16/10 is what ships — the portrait rule is
   kept for parity with the source). */
.eh-corridor__frame {
  position: relative;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border-radius: 1.5rem;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.6);
  background: #1C1C19;
}
@media (min-width: 640px) {
  .eh-corridor__frame { aspect-ratio: 16 / 10; }
}

/* ── THE CARD INSIDE A PANEL ───────────────────────────────────
   Same element as in the grid (moved, never cloned, so the tilt/hover/
   click handlers that main.js and animations.js attached by reference
   keep working). Only its layout changes: instead of a small white
   tile it fills the frame — photo full-bleed, copy over a dark scrim at
   the bottom, like the source's panels. */
.eh-corridor .service-card {
  position: absolute;
  inset: 0;
  display: block;
  background: transparent;
  border-radius: 0;
  box-shadow: none;
  /* Insurance: the site's fade-in systems (CSS .fade-in, motion.js's
     autoAlpha) must never leave a card hidden in here — the PANEL owns
     opacity. transform is deliberately left alone so the hover tilt in
     animations.js/main.js still works. */
  opacity: 1 !important;
  visibility: visible !important;
}
.eh-corridor .service-card:hover { transform: none; }

.eh-corridor .service-card__media {
  position: absolute;
  inset: 0;
  aspect-ratio: auto;
  clip-path: none;   /* the frame does the clipping now */
}
.eh-corridor .service-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.eh-corridor .service-card__body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: block;
  padding: 5.5rem 2.5rem 2rem;
  /* Solid enough at the text to guarantee contrast over ANY photo:
     at 0.94 over pure white the composite is still #2E2E2A-ish, so
     bone copy on it measures ~12:1 in the worst case. */
  background: linear-gradient(
    to top,
    rgba(18, 18, 16, 0.94) 0%,
    rgba(18, 18, 16, 0.88) 42%,
    rgba(18, 18, 16, 0.45) 74%,
    rgba(18, 18, 16, 0) 100%
  );
}
.eh-corridor .service-card h3 {
  color: var(--bone);
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 2.6vw, 2.35rem);
  line-height: 1.12;
  margin-bottom: 10px;
}
.eh-corridor .service-card p {
  color: rgba(245, 241, 234, 0.84);   /* ~10:1 on the scrim */
  font-size: 1rem;
  line-height: 1.6;
  max-width: 34rem;
  margin-bottom: 14px;
}
.eh-corridor .service-card__link {
  color: #A8D26A;                     /* 7.8:1 on the scrim */
  font-size: 0.875rem;
}

/* ── TAIL: what is left of the original section ────────────────
   Its header and its six cards now live in the corridor, so the
   section keeps only the "View All Services" button and the city pull.
   Without this it would open with 259px of padding above an empty grid. */
.eh-corridor-tail { padding-top: clamp(48px, 5vw, 88px) !important; }
.eh-corridor-tail .services-grid { display: none; }

/* ── PHONES ────────────────────────────────────────────────────
   There is deliberately NO mobile rule here. js/corridor.js refuses to
   build the corridor below 768px (full-screen blurred 3D panels are the
   classic mobile jank case, and the source kills its heaviest scene
   there too), so on a phone none of the selectors above exist and the
   normal .services-grid renders untouched.
   A `@media (max-width:767px){.eh-corridor{display:none}}` would be
   worse than nothing: a desktop visitor who narrows their window would
   have the six cards disappear, because by then the cards live inside
   this structure. */

