/* ============================================================
   SERVICES — fixed split-layout product showcase
   Colors come from the shared .room palette (css/palette.css) so
   this reads as the same room as Projects/Contact/Footer, not its
   own separate theme. Hero stays on its own dark theme.

   LAYOUT PHILOSOPHY (Apple product-page pattern): the section pins
   for one continuous scroll pass through all 5 services. Neither
   the left info panel nor the right media frame ever move or
   resize — only their CONTENT crossfades as the active service
   changes. There is no horizontal carousel/slide anywhere in this
   file; js/services.js only ever toggles opacity + a tiny
   translateY on text, and opacity on stacked media panels.

   NOTE ON HEIGHTS: .exhibition-pin subtracts var(--nav-h) from 100vh,
   and services.js offsets the ScrollTrigger pin start by the same
   amount, so the pinned content doesn't scroll in underneath the
   sticky navbar (see hero.css .hero height for the same convention).
   This only applies to the desktop pinned exhibition — the mobile/
   tablet .mobile-zone cards (below) are plain content-sized blocks in
   normal document flow, no viewport-height math involved at all.
============================================================ */
#services{
  position:relative;
  isolation:isolate;
  font-family:'Inter', sans-serif;
  -webkit-font-smoothing:antialiased;
  /* No background of its own — the shared .site-canvas backdrop
     (css/palette.css) shows straight through the whole section. */
}

/* Compact intro block — sized to its content rather than forced to
   fill the whole first screen. A full 100vh block here read as a
   mostly-empty slab with the heading floating in the middle; this
   keeps generous breathing room around the heading/subtitle without
   the dead space. Landing on #services via the navbar still never
   crops anything below: the pinned exhibition's own top state
   (first service, HUD ticks) is a complete, coherent view from its
   very first pixel, not a card sliced mid-frame, so there's nothing
   to protect against by forcing full height here.
   Padding is viewport-relative (clamp of a vh value, not an
   arbitrary fixed px) so it scales sensibly with the actual window:
   generous breathing room on tall screens, tighter on short ones —
   with floor/ceiling bounds so it's never cramped or excessive. */
#services .exhibition-lead{
  position:relative;
  z-index:1;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:clamp(64px, 9vh, 108px) 8vw clamp(20px, 2.6vh, 36px);
  text-align:center;
  box-sizing:border-box;
}
#services .exhibition-lead h2{
  font-family:'Fraunces', serif;
  font-weight:400;
  font-size:clamp(28px,4vw,48px);
  color:var(--room-text);
  max-width:720px;
  line-height:1.2;
}
#services .exhibition-lead p{
  font-size:13px;
  letter-spacing:0.2em;
  text-transform:uppercase;
  color:var(--room-text-muted);
  margin-top:28px;
}

/* ===================== DESKTOP EXHIBITION ===================== */
#services .exhibition{
  position:relative;
  z-index:1;
  display:block;
}

#services .exhibition-pin{
  position:relative;
  width:100%;
  height:calc(100vh - var(--nav-h));
  overflow:hidden;
  /* transparent: the shared .site-canvas background (palette.css)
     shows through uniformly */
  background:transparent;
}

/* ===================== SPLIT LAYOUT ===================== */
/* align-items:flex-start (not center) is the other half of fitting
   the heading + first service into one screen: the pin box is a
   full calc(100vh - navH) tall "stage", so centering the content
   inside it — as this used to do — left a large slab of empty
   space above it purely from that centering, no matter how tight
   the heading block above got. Anchoring near the top instead (with
   a viewport-relative offset, clear of the HUD ticks in the corner)
   means the content's own vertical position no longer depends on
   its height, which also keeps every zone's content starting at the
   exact same Y position during the scrub — a small consistency
   improvement, not just a fix for the entry view. */
#services .exhibition-split{
  position:relative;
  z-index:1;
  height:100%;
  width:100%;
  max-width:1400px;
  margin:0 auto;
  padding:clamp(72px, 11vh, 132px) 6vw 0;
  display:flex;
  align-items:flex-start;
  gap:clamp(32px, 5vw, 96px);
}

/* -- LEFT: permanently fixed info panel. This element itself never
      moves — js/services.js only ever animates opacity + translateY
      on it (max 10px, 350-450ms), never its position in the flex
      layout, so it can never read as "sliding". -- */
#services .split-left{
  position:relative;
  flex:0 0 auto;
  width:min(42%, 480px);
  z-index:2;
  /* Matches .split-right's own height formula exactly (see below) so
     both columns start at the same Y (the row's align-items:flex-start
     is untouched) and share an identical height. justify-content:center
     then centers this column's content as one block within that height,
     landing its visual midpoint on the media card's visual midpoint —
     without moving/resizing the media card and without touching the
     spacing between the elements inside this column. */
  height:min(60vh, 620px);
  display:flex;
  flex-direction:column;
  justify-content:center;
}

#services .split-number{
  display:flex;
  align-items:baseline;
  gap:6px;
  font-family:'Fraunces', serif;
  font-size:15px;
  letter-spacing:0.04em;
  color:var(--room-text);
  margin-bottom:18px;
}
#services .split-number-total{
  font-size:12px;
  color:rgba(47,36,27,0.42);
}

/* -- RIGHT: permanently fixed media frame. Fixed size regardless of
      which zone is active, so there is zero layout shift when the
      active service changes — only the stacked .zone-media panels
      inside it crossfade opacity (see below). -- */
/* The panel itself now reads as a premium display case — soft glass
   surface, thin champagne border, floating shadow, rounded corners —
   rather than a bare invisible box behind the footage. */
#services .split-right{
  position:relative;
  flex:1 1 auto;
  height:min(60vh, 620px);
  min-height:360px;
  display:flex;
  align-items:center;
  justify-content:center;
  border-radius:26px;
  border:1px solid rgba(140,98,57,0.18);
  background:linear-gradient(180deg, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0.2) 100%);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.6) inset,
    0 42px 80px -36px rgba(47,36,27,0.30),
    0 12px 30px -18px rgba(47,36,27,0.14);
  overflow:hidden;
}

/* One quiet, identical ambient highlight behind every zone's media —
   not colour-coded per service (the real footage now carries that),
   just a soft "studio floor" glow so the frame never looks flat.
   Pure gradient, no blur filter, effectively free to paint. */
#services .split-right::before{
  content:"";
  position:absolute;
  inset:0;
  background:radial-gradient(ellipse 60% 55% at 50% 55%, rgba(140,98,57,0.10) 0%, rgba(140,98,57,0) 72%);
  pointer-events:none;
}

/* ===================== ZONE MEDIA (real equipment video/image) =====================
   All 5 panels are stacked in the exact same box via position:absolute
   + a shared inset — identical size for every service. js/services.js
   toggles only the .active class (opacity 0 -> 1 crossfade); nothing
   here ever changes size, position, or triggers a reflow. The inset
   (instead of 0) is what actually creates the "equal padding on every
   side" showcase margin — a parent's own padding wouldn't do this for
   an absolutely-positioned child, since inset is measured from the
   padding edge regardless. object-fit:contain keeps every unit fully
   framed regardless of its native aspect ratio. */
#services .zone-media{
  position:absolute;
  inset:clamp(16px, 2.2vw, 28px);
  display:flex;
  align-items:center;
  justify-content:center;
  z-index:1;
  opacity:0;
  pointer-events:none;
  border-radius:18px;
  transition:opacity 0.4s ease;
}
#services .zone-media.active{
  opacity:1;
  z-index:2;
}
#services .zone-media video,
#services .zone-media img{
  width:100%;
  height:100%;
  object-fit:contain;
  object-position:center;
  border-radius:18px;
  /* The luxury frame itself — thin champagne edge, soft inner
     highlight (the "glass" catch-light along the top), and an
     elegant floating shadow beneath. Deliberately restrained: no
     heavy border weight, no saturated glow. */
  border:1.5px solid rgba(140,98,57,0.28);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.55) inset,
    0 28px 42px -22px rgba(47,36,27,0.32),
    0 6px 16px -8px rgba(47,36,27,0.14);
  background:rgba(255,255,255,0.3);
}

/* ===================== CONTENT (left panel) ===================== */
#services .content-eyebrow{
  font-size:11px;
  letter-spacing:0.22em;
  text-transform:uppercase;
  color:var(--room-text-muted);
  margin-bottom:16px;
}
#services .content-title{
  font-family:'Fraunces', serif;
  font-weight:400;
  font-size:clamp(32px, 3.4vw, 50px);
  line-height:1.06;
  letter-spacing:-0.01em;
  color:var(--room-text);
  margin-bottom:18px;
}
#services .content-desc{
  font-size:14.5px;
  line-height:1.7;
  color:rgba(47,36,27,0.72);
  font-weight:300;
  margin-bottom:22px;
}

#services .content-caps{
  list-style:none;
  display:flex;
  flex-wrap:wrap;
  border-top:1px solid var(--room-border);
  padding-top:14px;
  margin-bottom:20px;
}
#services .content-caps li{
  position:relative;
  font-size:12px;
  letter-spacing:0.02em;
  color:rgba(47,36,27,0.7);
  padding-right:16px;
  margin-right:16px;
  margin-bottom:8px;
}
#services .content-caps li::after{
  content:"";
  position:absolute;
  right:-8px; top:50%;
  width:1px; height:11px;
  background:var(--room-border);
  transform:translateY(-50%);
}
#services .content-caps li:last-child{ margin-right:0; padding-right:0; }
#services .content-caps li:last-child::after{ display:none; }

/* ===================== TICKS + SCROLL HINT ===================== */
/* Progress ticks — a persistent nav control, not part of the fading
   content, so it sits fixed in its own corner and only its active
   state changes. Doubles as click-to-jump navigation. */
#services .hud-ticks{
  position:absolute;
  top:6vh;
  right:6vw;
  z-index:10;
  display:flex;
  flex-direction:column;
  gap:10px;
  align-items:flex-end;
}
#services .hud-tick{
  width:16px; height:1px;
  background:rgba(47,36,27,0.22);
  cursor:pointer;
  transition:width 0.4s ease, background 0.4s ease;
}
#services .hud-tick.active{ width:32px; background:var(--room-accent); }

/* Replaces the old "Scroll to explore" hint at the same position —
   this is now a real, direct navigation control (click = swap service
   immediately, see js/services.js), not a hint about scrolling,
   because there's no more scroll-driven advancement to hint about. */
#services .exhibition-controls{
  position:absolute;
  bottom:5vh;
  left:50%;
  transform:translateX(-50%);
  z-index:10;
  display:flex;
  align-items:center;
  gap:20px;
}
#services .exhibition-nav{
  width:44px;
  height:44px;
  border-radius:50%;
  border:1px solid var(--room-border);
  background:rgba(255,255,255,0.55);
  color:var(--room-text-muted);
  display:flex;
  align-items:center;
  justify-content:center;
  cursor:pointer;
  transition:border-color 0.25s ease, color 0.25s ease, transform 0.25s ease;
}
#services .exhibition-nav svg{ width:18px; height:18px; }
#services .exhibition-nav:hover{
  border-color:var(--room-accent);
  color:var(--room-accent);
  transform:translateY(-1px);
}
#services .exhibition-nav:active{ transform:translateY(0); }

/* 1024px, not 900px: matches the JS matchMedia switch in services.js
   and every other section's mobile/tablet cutoff. Was 900px, which left
   the 901-1023px tablet band running the desktop pin (a ~10-screen-height
   captive scroll) — that's the reported "hard scroll/stoppage" on tablet.
   Tablets now get the same lite card flow as phones. */
@media (max-width: 1023px){
  #services .exhibition{ display:none; }
}

/* ===================== MOBILE EXHIBITION ===================== */
#services .exhibition-mobile{ display:none; }

@media (max-width: 1023px){
  /* Tighter intro block to match the density pass everywhere else on
     mobile — was riding a clamp tuned for desktop's more generous
     vertical rhythm. Cut a further ~15%, then another ~15% this pass —
     this is the "Services heading -> first service" gap specifically
     called out for compaction. */
  #services .exhibition-lead{
    padding:clamp(28px, 4vh, 44px) 6.5vw clamp(8px, 1.2vh, 14px);
  }
  #services .exhibition-lead p{
    margin-top:12px;
  }

  #services .exhibition-mobile{
    display:block;
    position:relative;
    z-index:1;
  }
  /* Rebuilt as a plain content-first card: no viewport-height sizing,
     no flex/align-items positioning trick, no absolute-positioned
     media floating over a bottom-anchored text block. Every piece
     (image, zone label, heading, description, features, pagination)
     is now a normal stacked block in document-flow order, so the
     zone's own height is simply whatever its content needs — nothing
     reserves empty space, and nothing can ever overlap anything else.
     padding-top is intentionally small: it's the "gap between this
     zone and whatever's above it" (either the section heading, for
     the first zone, or the previous zone's pagination dots) —
     border-bottom is the visual divider between zones instead of
     reserved empty space. */
  #services .mobile-zone{
    position:relative;
    padding:18px 4vw 24px;
    border-bottom:1px solid var(--room-border);
  }
  /* .exhibition-mobile used to be its own nested scroll container
     (overflow-y:auto + max-height) with scroll-snap-type:y mandatory
     forcing a hard stop at each zone's boundary (scroll-snap-align on
     .mobile-zone, removed above). That's exactly what read as the
     page "getting stuck"/scroll-trapped while scrolling through
     Services on phones and small tablets — every zone required its
     own separate scroll gesture to clear the snap point instead of
     one continuous scroll. Removed entirely: .exhibition-mobile is
     now just a plain block of stacked .mobile-zone sections in
     ordinary page flow, so the whole section scrolls exactly like
     every other section on the page, at native scroll speed, with no
     trigger/pin/snap of any kind. */
  #services .mobile-zone::before{
    content:"";
    position:absolute;
    inset:0;
    background:radial-gradient(circle at 70% 30%, rgba(140,98,57,0.12), transparent 60%);
    pointer-events:none;
  }

  /* The ONE deliberate exception to "no absolute positioning": the
     "01/05" corner badge. It's absolutely positioned relative to THIS
     wrapper only (not the whole zone), so it can only ever sit over
     the image itself — it has no way to reach or overlap the zone
     label/heading/description below it, which are later siblings in
     normal flow, entirely outside this wrapper's box. */
  #services .mobile-media-wrap{
    position:relative;
    width:100%;
    margin-bottom:20px; /* Image -> Zone Label */
    border-radius:16px;
  }

  /* Same "showroom frame" idea as desktop — object-fit:contain so the
     unit is never cropped — but sized by aspect-ratio against the
     card's own width instead of a viewport-height fraction, so it
     scales naturally with the card and settles at roughly 40-45% of
     the card's total height instead of an arbitrary vh slice. */
  #services .mobile-zone .zone-media{
    position:relative;
    /* The shared base rule (#services .zone-media, used by desktop's
       absolutely-positioned split-right panels) sets
       inset:clamp(16px, 2.2vw, 28px) to size itself inside an
       absolute-positioned parent. That property doesn't just vanish
       once position switches to relative here — for a relatively
       positioned element, top/right/bottom/left (inset's longhands)
       instead become a VISUAL OFFSET from its normal flow position,
       and when left+right are both set, left wins. So without this
       reset, every mobile zone-media box was silently shifted right
       (and down) by 16-28px on top of its already-centered layout —
       exactly the "attached to the right edge" / off-center bug.
       Resetting inset cancels that inherited offset entirely. */
    inset:auto;
    width:100%;
    aspect-ratio:16 / 10;
    display:flex;
    align-items:center;
    justify-content:center;
    border-radius:16px;
    overflow:hidden;
    opacity:0;
    transition:opacity 0.4s ease;
  }
  /* Each mobile-zone only ever contains its own single zone-media (no
     stacking needed like the desktop split-right box), so it simply
     shows whenever its parent zone scrolls into view. */
  #services .mobile-zone.in-view .zone-media{ opacity:1; }
  #services .mobile-zone .zone-media video,
  #services .mobile-zone .zone-media img{
    width:100%;
    height:100%;
    object-fit:contain;
    object-position:center;
    border-radius:16px;
    /* Same luxury-frame treatment as desktop's split-right media, scaled
       down slightly for the smaller mobile showcase box. */
    border:1.5px solid rgba(140,98,57,0.28);
    box-shadow:
      0 1px 0 rgba(255,255,255,0.55) inset,
      0 22px 32px -18px rgba(47,36,27,0.32),
      0 5px 12px -6px rgba(47,36,27,0.14);
    background:rgba(255,255,255,0.3);
  }

  #services .mobile-content{
    position:relative;
    z-index:5;
    width:100%;
    opacity:0;
    transform:translateY(10px);
    transition:opacity 0.4s ease, transform 0.4s ease;
  }
  #services .mobile-zone.in-view .mobile-content{ opacity:1; transform:translateY(0); }

  #services .mobile-index{
    position:absolute;
    top:10px; right:10px;
    z-index:5;
    font-family:'Fraunces', serif;
    font-size:12px;
    color:rgba(47,36,27,0.75);
    background:rgba(251,248,242,0.85);
    padding:3px 9px;
    border-radius:999px;
  }
  #services .mobile-index strong{ color:var(--room-text); }

  #services .mobile-eyebrow{
    font-size:11.5px;
    letter-spacing:0.2em;
    text-transform:uppercase;
    color:rgba(47,36,27,0.5);
    margin-bottom:8px; /* Zone Label -> Heading */
  }
  #services .mobile-title{
    font-family:'Fraunces', serif;
    font-weight:400;
    font-size:clamp(20px, 5.6vw, 24px);
    line-height:1.08;
    color:var(--room-text);
    margin-bottom:12px; /* Heading -> Description */
  }
  #services .mobile-desc{
    font-size:15px;
    line-height:1.55;
    color:rgba(47,36,27,0.72);
    font-weight:300;
    margin-bottom:18px; /* Description -> Features */
    max-width:520px;
  }
  #services .mobile-caps{
    list-style:none;
    border-top:1px solid var(--room-border);
    padding-top:12px;
    margin-bottom:18px; /* Features -> Pagination */
    display:flex;
    flex-wrap:wrap;
    gap:8px 14px;
  }
  #services .mobile-caps li{
    font-size:12.5px;
    color:rgba(47,36,27,0.68);
    position:relative;
    padding-right:14px;
  }
  #services .mobile-caps li::after{
    content:"";
    position:absolute; right:-7px; top:50%;
    width:1px; height:10px;
    background:var(--room-border);
    transform:translateY(-50%);
  }
  #services .mobile-caps li:last-child::after{ display:none; }

  /* No longer absolutely positioned — the last item in normal flow,
     so "Card Bottom" spacing (.mobile-zone's own padding-bottom) is
     the only space between it and the divider/next card. */
  #services .mobile-progress{
    position:relative;
    display:flex;
    gap:7px;
  }
  #services .mobile-progress span{
    width:14px; height:1px;
    background:rgba(47,36,27,0.22);
    transition:width 0.4s ease, background 0.4s ease;
  }
  #services .mobile-progress span.active{ width:26px; background:var(--room-accent); }
}

/* ===================== TABLET (641-1023px) =====================
   A dedicated tier, not desktop spacing scaled down and not the same
   numbers as phones: wider card (93% vs mobile's ~92%), a shorter/
   wider image aspect ratio (more editorial, "slightly smaller" than
   desktop in proportion), and every type size and spacing value one
   deliberate notch up from the mobile tier above. Declared after the
   base <=1023px block on purpose — equal specificity, later in source,
   so it wins for the 641-1023px range while phones (<=640px) keep the
   base numbers untouched. Upper bound raised from 900px to 1023px
   alongside the JS pin threshold move, so the full tablet band (which
   used to get the desktop pin instead) now gets this tier's styling. */
@media (min-width:641px) and (max-width:1023px){
  #services .mobile-zone{ padding:22px 3.5vw 28px; }
  #services .mobile-media-wrap{ margin-bottom:24px; }
  #services .mobile-zone .zone-media{ aspect-ratio:16 / 9; }
  #services .mobile-eyebrow{ font-size:12px; margin-bottom:10px; }
  #services .mobile-title{ font-size:clamp(26px, 3.6vw, 30px); margin-bottom:14px; }
  #services .mobile-desc{ font-size:16px; margin-bottom:20px; }
  #services .mobile-caps{ margin-bottom:20px; }
  #services .mobile-caps li{ font-size:13px; }
}

@media (prefers-reduced-motion: reduce){
  #services .zone-media,
  #services .mobile-content,
  #services .hud-tick,
  #services .exhibition-nav{
    transition-duration:0.01ms !important;
  }
}
