/* Michal Kašpar — "What I do" scroll-stack services section
   ──────────────────────────────────────────────────────────
   Pattern: vertical accordion list where each service header
   pins to the navbar as you scroll. Headers stack progressively
   at incrementing `top` offsets so all previously-passed
   services remain visible at the top of the viewport. When the
   section ends, every sticky header releases together. */

:root {
  --nav-h: clamp(64px, 8vh, 88px);
  --service-head-h: clamp(64px, 8vh, 84px);
}

/* Override .reel defaults — this reel is tall and must allow
   sticky descendants to escape (no overflow:hidden). */
.reel.services {
  height: auto;
  min-height: 100dvh;
  overflow: visible;
  /* Dotted ambient applied directly with fixed attachment so the
     dot grid aligns with the closer + cards + neighbouring
     sections. */
  background: var(--bg);
  padding: 0;
  scroll-snap-stop: normal;
}

/* ── Section intro ──────────────────────────────────────── */
.services-intro {
  position: relative;
  /* All section kickers (Philosophy / Services / FAQ) anchor at the
     same vertical distance from their respective top borders. Pads
     match the FAQ wrap so the three labels read on a single
     imaginary horizontal grid line. */
  padding: clamp(20px, 2.6vh, 30px) var(--edge-x) clamp(48px, 8vh, 96px);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 4vw, 80px);
  /* Stretch the row so the two children can anchor independently
     — kicker to the top of the left column, paragraph to the
     bottom of the right column. Same vocabulary as the FAQ wrap. */
  align-items: stretch;
  min-height: 80vh;
  border-top: 1px solid var(--line);
}
.services-kicker {
  font-family: var(--font-mono);
  font-size: var(--text-base);
  letter-spacing: 0.02em;
  font-weight: 500;
  text-transform: uppercase;
  color: var(--fg);
  align-self: start;
}
.services-intro-text {
  /* Same scale as the in-card body copy (~20px) — small, easy to
     read; the headline weight comes from its placement at the
     bottom of the column, not its font-size. */
  font-size: var(--text-base);
  font-weight: 500;
  letter-spacing: -0.008em;
  line-height: 1.5;
  color: var(--fg);
  max-width: 36ch;
  text-wrap: pretty;
  margin: 0;
  /* Anchor to the bottom-right column. */
  align-self: end;
}

/* ── List wrapper ───────────────────────────────────────── */
.services-list {
  position: relative;
  /* Lock duration — short hold (~30vh) before vision releases.
     Trade-off between lock-feel and post-release dark gap. */
  padding-bottom: 30vh;
}

/* ── Single service ─────────────────────────────────────── */
/* Each card is itself position:sticky with an incrementing top
   and z-index. Later cards sit ON TOP of earlier ones, so as the
   user scrolls, card N+1 visually slides up from below and
   covers card N's body — only the head of N remains peeking
   above (because N+1 sticks lower down). All cards release
   together when .services-list bottom is reached. */
.service {
  position: sticky;
  /* Solid --bg. Earlier cards stay opaquely covered as the
     stack progresses. */
  background: var(--bg);
  /* Height set per nth-of-type below — varies per card so all
     sticky elements (cards 1–5 + closer) hit their unstick
     threshold at the same scroll position. We pin EXPLICIT
     heights (not min-height) so the accordion math is identical
     whether images are present, loading, missing, or replaced
     with a taller/shorter asset. Overflow:hidden anchors the
     visible footprint to the calculated value. */
  padding: 0 var(--edge-x);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.service:first-of-type {
  /* Section start: full-width top border, same idea as FAQ
     wrap's border-top. */
  border-top: 1px solid var(--line);
}
.service:not(:first-of-type) {
  /* Need positioning context for the half-width divider pseudo. */
  position: sticky; /* stays sticky */
}
.service:not(:first-of-type)::after {
  /* Inter-card divider lives in the right half only — mirrors the
     short inner dividers in FAQ between questions. */
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  right: 0;
  height: 1px;
  background: var(--line);
  pointer-events: none;
  z-index: 1;
}
.service:last-of-type {
  border-bottom: 1px solid var(--line);
}

/* Pin top + flow height (= unstick threshold K, same for all).
   K = nav-h + 100vh  — i.e. card 1 is exactly one viewport tall.
   So height_N = K - top_N = 100vh − (N-1)·head-h. */
.service:nth-of-type(1) {
  top: var(--nav-h);
  z-index: 1;
  height: 100vh;
}
.service:nth-of-type(2) {
  top: calc(var(--nav-h) + 1 * var(--service-head-h));
  z-index: 2;
  height: calc(100vh - 1 * var(--service-head-h));
}
.service:nth-of-type(3) {
  top: calc(var(--nav-h) + 2 * var(--service-head-h));
  z-index: 3;
  height: calc(100vh - 2 * var(--service-head-h));
}
.service:nth-of-type(4) {
  top: calc(var(--nav-h) + 3 * var(--service-head-h));
  z-index: 4;
  height: calc(100vh - 3 * var(--service-head-h));
}
.service:nth-of-type(5) {
  top: calc(var(--nav-h) + 4 * var(--service-head-h));
  z-index: 5;
  height: calc(100vh - 4 * var(--service-head-h));
}

/* Head — just a regular row inside the card (NOT sticky now). */
.service-head {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: clamp(20px, 3vw, 56px);
  min-height: var(--service-head-h);
  /* Padding mirrors .services-intro + .faq-kicker so the SERVICES
     kicker sits at the same vertical inset as PHILOSOPHY and FAQ. */
  padding: clamp(20px, 2.6vh, 30px) 0;
  flex: 0 0 auto;
}
/* Section kicker — "SERVICES" rides in the left column of the FIRST
   service card's header. Anchored to the TOP of the head row (not
   centred with the service name) so all three section labels —
   PHILOSOPHY, SERVICES, FAQ — read at the same vertical distance
   from their respective top borders. */
/* Section kicker — "SERVICES" rides in the left column of the FIRST
   service card's header (a real element so it can run decode-reveal;
   only the first card has the span). Anchored to the TOP of the head
   row (not centred with the service name) so all three section
   labels — PHILOSOPHY, SERVICES, FAQ — read at the same vertical
   distance from their respective top borders. */
.service-head .service-kicker {
  font-family: var(--font-mono);
  font-size: var(--text-base);
  letter-spacing: 0.02em;
  font-weight: 500;
  text-transform: uppercase;
  color: var(--fg);
  grid-column: 1;
  align-self: start;
}
.service-head .service-name {
  /* Title lives in the right half of the page — aligns with the
     body content column underneath (price + paragraphs + image). */
  grid-column: 2;
}

.service-name {
  font-size: var(--text-lg);
  font-weight: 500;
  letter-spacing: -0.012em;
  color: var(--fg);
  margin: 0;
  line-height: 1.1;
}

/* Price tag — lives in the head row, right column. Sits on the
   same baseline as the service name and its left edge aligns
   with the body content column below (viewport midline). It is
   visible the entire time this service is the active one (i.e.
   pinned on top of the stack) and fades out the moment the next
   service stacks over it. Because it lives in the head (which
   is itself part of the sticky card), it stays put while the
   user scrolls — no jumping down with the body content. */
.service-price {
  justify-self: start;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text-primary) 55%, transparent);
  white-space: nowrap;
  /* Visible by default — only fades out once the next service
     stacks over this one (i.e. card has been collapsed). */
  opacity: 1;
  transition: opacity 320ms ease;
  pointer-events: none;
}
.service-price .service-price-val {
  /* Match the prefix style — same mono size, same dimmed colour,
     so the whole price line reads as a single quiet caption. */
  color: color-mix(in srgb, var(--color-text-primary) 55%, transparent);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  font-weight: 500;
  margin-left: 8px;
}

/* +/− toggle removed — service open/close state is purely
   scroll-position driven now, no click affordance. */

/* ── Service body ───────────────────────────────────────── */
/* Body is part of the card and always visible. The card stacking
   (later cards on top via z-index + opaque background) is what
   visually "covers" earlier service bodies — no opacity needed.
   Grid is split 50/50 so the right-hand content column starts
   exactly at viewport midline, aligning the paragraphs' left
   edge with the image's left edge. */
.service-body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(20px, 3vw, 56px);
  padding: clamp(20px, 3vh, 40px) 0 0;
  flex: 1 1 auto;
  min-height: 0;
}

.service-body-empty {
  /* left column spacer, aligns body content with the right
     half of the head row (past the num column) */
}

.service-body-content {
  /* Lives in the right half of the body grid. Paragraphs and
     image share the left edge of this column = viewport midline.
     Flex column so the media slot can shrink to fit the card's
     fixed height regardless of image presence. */
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 3vh, 36px);
  width: 100%;
  min-height: 0;
}

.service-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 3vw, 56px);
}
.service-cols p {
  font-size: var(--text-base);
  font-weight: 400;
  line-height: 1.62;
  color: var(--color-text-soft);
  margin: 0;
  text-wrap: pretty;
}

.service-media {
  width: 100%;
  aspect-ratio: 16 / 9;
  /* Flex item — allowed to shrink so it never pushes the card
     past its fixed height. The 16:9 ratio is the desired size;
     min-height: 0 lets the card clip the bottom of the slot
     gracefully on tight viewports instead of breaking the
     accordion stacking math. */
  flex: 0 1 auto;
  min-height: 0;
  margin-top: 0;
  border-radius: 20px;
  overflow: hidden;
  /* Override the dark .media-ph base — user wants a visibly
     lighter placeholder so the image slot is obvious. */
  background-color: var(--color-bg-primary);
  background-image: repeating-linear-gradient(
    45deg,
    color-mix(in srgb, var(--color-text-primary) 5%, transparent) 0px,
    color-mix(in srgb, var(--color-text-primary) 5%, transparent) 10px,
    transparent 10px,
    transparent 20px
  );
}
.service-media.media-ph::after {
  color: color-mix(in srgb, var(--color-text-primary) 65%, transparent);
  bottom: 18px;
  left: 20px;
}
.service-media img,
.service-media video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ── Click-to-play video variant ────────────────────────── */
.service-media--video {
  position: relative;
  /* No striped placeholder bg — the video poster + actual video
     fill the slot. */
  background: transparent;
  background-image: none;
}
.service-media-play {
  /* Circular play affordance, centred over the poster frame.
     Disappears once the video starts (handled in JS). */
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(72px, 7vw, 104px);
  height: clamp(72px, 7vw, 104px);
  border-radius: 50%;
  background: color-mix(in srgb, var(--color-pure-black) 45%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-text-primary) 70%, transparent);
  color: var(--color-pure-white);
  cursor: pointer;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: background 220ms ease, border-color 220ms ease,
              transform 280ms cubic-bezier(0.16, 1, 0.3, 1),
              opacity 240ms ease;
  z-index: 2;
}
.service-media-play svg {
  width: 36%;
  height: 36%;
  fill: currentColor;
  /* Optical centre the triangle — geometric centre sits ~2 px
     left of optical centre on a play glyph. */
  margin-left: 6%;
}
.service-media-play:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--color-pure-black);
  transform: translate(-50%, -50%) scale(1.08);
}
.service-media--video.is-playing .service-media-play {
  opacity: 0;
  pointer-events: none;
}

/* ── Closing zone — 6th sticky element ────────────────────
   Lives INSIDE .services-list as the final sticky child. Pins
   below the 5 stacked service heads with a higher z-index, so
   it covers service 05's body the same way each service covers
   the previous one. Stays pinned for ~100vh of scroll (provided
   by .services-list's padding-bottom), then everything releases
   together and the next reel appears. */
/* ─────────────────────────────────────────────────────────
   Big claim — its own 100vh reel after Services.
   Full-viewport yellow plate with the claim centred on it.
   The hover-image plate (be-freaky-style) lives inside.
   ───────────────────────────────────────────────────────── */
/* ─────────────────────────────────────────────────────────
   Closing zone — silent yellow "fake card" inside services-list.
   Pins below the last service head, slides up to cover card 3's
   body, then releases together with all sticky cards when
   services-list bottom is reached. No content — the claim
   lives in the next reel (big-claim-full). This plate is just
   the colour transition.
   ───────────────────────────────────────────────────────── */
.services-closer {
  position: sticky;
  top: calc(var(--nav-h) + 3 * var(--service-head-h));
  z-index: 10;
  background: var(--accent);
  /* Flow height tuned so the closer's unstick point (top + height)
     matches the 3 service cards' (nav-h + 100vh). */
  min-height: calc(100vh - 3 * var(--service-head-h));
}
.closer-inner {
  height: calc(100vh - var(--nav-h) - 3 * var(--service-head-h));
}

/* ─────────────────────────────────────────────────────────
   Vision layer — yellow plate that rises through the viewport,
   covering the cards as it climbs. Pinned at top: nav-h with
   z-index 5 (between cards at 1–3 and the silent closer at 10).
   Hosts the big claim + cursor-follower image plate.
   ───────────────────────────────────────────────────────── */
.vision-layer {
  position: sticky;
  top: var(--nav-h);
  /* Above the closer (z 10) so the claim text reads over the
     yellow band closer slid up earlier; the two yellows blend
     visually so user perceives ONE continuous plate. */
  z-index: 11;
  background: var(--accent);
  /* Flow height = 100vh + lock duration. Pins when its natural
     top crosses y=nav-h, then stays pinned for the lock window. */
  min-height: 100vh;
}
.vision-inner {
  /* Visible band of the pinned layer = full viewport below nav. */
  height: calc(100vh - var(--nav-h));
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 clamp(24px, 4vw, 80px);
  overflow: hidden;
}
.vision-layer .closer-claim {
  font-size: var(--text-2xl);
  font-weight: 500;
  letter-spacing: -0.025em;
  line-height: 1.05;
  color: var(--color-pure-black);
  margin: 0;
  text-align: center;
  position: relative;
  z-index: 2;
  max-width: none;
}
.vision-layer .closer-claim .em { color: var(--color-pure-black); }
.vision-layer .closer-claim .lr-line { white-space: nowrap; }

/* ── Mobile ─────────────────────────────────────────────── */
@media (max-width: 760px), (max-width: 1024px) and (orientation: portrait) {
  .services-intro {
    grid-template-columns: 1fr;
    gap: 22px;
  }
  .services-intro {
    padding-top: calc(var(--nav-h) + 48px);
  }
  /* NOTE: card 1 must NOT get padding-top here — when the card is
     pinned, top padding shoves the "Services" head DOWN inside the
     sticky box, dropping it below the heads of cards 2/3 (which pin
     higher). That was the bug where "Services" vanished from the
     stack. Pre-stack breathing room comes from .services-intro
     (80vh) above, so none is needed on the card itself. */
  /* Inter-service dividers run full-bleed on mobile (desktop keeps
     them to the right half only). */
  .service:not(:first-of-type)::after {
    left: 0;
  }
  .service-head {
    grid-template-columns: 1fr;
    padding: 14px 0;
    gap: 6px;
  }
  .service-head .service-name {
    /* On mobile the head collapses to a single column — drop the
       right-half grid placement. */
    grid-column: auto;
  }
  .service-price {
    margin-left: 0;
    font-size: var(--text-xs);
  }
  .service-body {
    grid-template-columns: 1fr;
    gap: 0;
  }
  .service-body-empty { display: none; }
  .service-body-content {
    margin-left: 0;
  }
  .service-cols {
    grid-template-columns: 1fr;
    gap: 18px;
    margin-left: 0;
  }
  /* Mobile-only price echo no longer needed — the single price
     row in body content handles both desktop and mobile. */
  .service-price-mobile { display: none; }
  .service {
    /* Card-cover accordion works on mobile too, but here CONTENT
       drives the card height (no fixed viewport-tall cards). The
       per-card `height` from the nth-of-type rules is MORE specific
       than a bare `.service`, so it needs !important to actually
       collapse to content height — otherwise cards stay locked to
       100vh-derived heights, their bodies overflow VISIBLY, and the
       stacked-head effect falls apart (this was the bug: heads not
       staying pinned). overflow:hidden clips each covered body
       cleanly behind the next card as it slides up. */
    height: auto !important;
    /* Each card spans at least one viewport so the NEXT card always
       fully covers the previous body as it slides up (otherwise the
       tallest card — #1 — peeks a sliver below the shorter ones).
       Content taller than 100vh still grows the card (min-height,
       not height), so nothing is ever clipped. */
    min-height: 100vh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  .service-body { display: grid; min-height: 0; }
  .service-body-content { display: grid; }
  .service-media { flex: none; aspect-ratio: 16 / 9; margin-top: clamp(16px, 3vh, 32px); }

  /* ── Vision claim (yellow plate) ──────────────────────────
     --text-2xl bottoms out at 60px, far too wide for the
     no-wrap claim lines on a phone (they ran off both edges).
     Pin an explicitly mobile-scaled size that keeps both
     authored lines inside the viewport, and tighten the inner
     padding so there's more room for the type. */
  .vision-layer .vision-inner { padding: 0 18px; }
  .vision-layer .closer-claim {
    font-size: clamp(23px, 6.8vw, 42px);
    line-height: 1.1;
    letter-spacing: -0.02em;
  }
}
@media (min-width: 761px) {
  /* placeholder — no desktop-only overrides needed */
}

/* ─────────────────────────────────────────────────────────
   Cursor-follower image plate
   ──────────────────────────────────────────────────────────
   A square thumbnail rides the mouse anywhere over the big
   claim, rotating through a small set of placeholder frames.
   Be-freaky-style — the image sits ON TOP of the claim, the
   claim text reads through where the image isn't.

   The plate is absolutely positioned inside .vision-inner,
   which is position: relative + overflow: hidden (set above).
   ───────────────────────────────────────────────────────── */
.claim-hover {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  /* Static container — frames are positioned absolutely
     inside it via JS-managed transforms. No cursor follower. */
}
.claim-hover-frame {
  position: absolute;
  top: 0;
  left: 0;
  width: clamp(280px, 28vw, 420px);
  aspect-ratio: 4 / 3;
  opacity: 0;
  pointer-events: none;
  will-change: transform, opacity;
  /* Reveal is instant (JS flips opacity to 1). Position,
     rotation, scale, momentum + lifetime fade all run in a JS
     rAF loop. */
}
.claim-hover-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 12px;
}

/* ── Touch / small-screen ──
   No cursor → no follower. Hide it cleanly so it can't ever
   show on tap and won't take any layout. */
@media (max-width: 760px), (max-width: 1024px) and (orientation: portrait), (hover: none) {
  .claim-hover { display: none !important; }
}
