/* ==========================================================================
   ICGE motion system

   One shared vocabulary for the whole site. Nothing here changes layout,
   type, colour, spacing or imagery - it only governs how existing elements
   arrive and respond.

   Architecture note: the Claude Design runtime re-renders its templates and
   strips attributes and classes it does not own, so this system never tags
   runtime-rendered elements. All state lives in two places it cannot touch:
   a class on <html>, and one inherited custom property (--icge-in) set on
   the authored [data-reveal] section. Everything else is pure CSS.

   Scoped to html.icge-js, so with JavaScript disabled the site renders
   fully visible and completely static.
   ========================================================================== */

:root {
  /* Easing - a confident settle, never springy */
  --icge-ease:     cubic-bezier(0.22, 0.61, 0.36, 1);
  --icge-ease-out: cubic-bezier(0.16, 1, 0.30, 1);

  /* Three tiers: fast = micro-interaction, medium = text, slow = imagery */
  --icge-fast: 280ms;
  --icge-med:  560ms;
  --icge-slow: 900ms;

  --icge-rise: 22px;   /* reveal travel */
  --icge-step: 90ms;   /* stagger between siblings */
}

/* Mobile: shorter travel, quicker steps - premium but fast */
@media (max-width: 767px) {
  :root {
    --icge-med:  460ms;
    --icge-slow: 720ms;
    --icge-rise: 12px;
    --icge-step: 70ms;
  }
}

/* --------------------------------------------------------------------------
   1. Page load / hero imagery.

   A one-shot keyframe rather than a JS-toggled transition: the hero copy
   already opens this way (icgeUp), and a keyframe cannot leave the page
   stranded invisible if a class never lands. The <body> is deliberately NOT
   faded as a whole - gating the entire document behind one transition is not
   worth the blank-page risk for a effect this subtle.

   The image starts fractionally over-scaled and settles to rest on a slower
   curve than the text, so the picture reads as weightier. Plays once.
   -------------------------------------------------------------------------- */
@keyframes icgeArt {
  from { opacity: 0; transform: scale(1.055); }
  to   { opacity: 1; transform: none; }
}
html.icge-js .hero-art-desktop,
html.icge-js .hero-art-mobile {
  animation: icgeArt 1600ms var(--icge-ease-out) both;
}

/* --------------------------------------------------------------------------
   3. Scroll reveal, with stagger.

   Sections keep their authored [data-reveal] hook. JS sets --icge-in: 1 on
   the section when it enters view; the children read that inherited value,
   so nothing is written to the children themselves.

   .svc-stage is excluded: it contains the sticky Services image frame, and
   a transform on an ancestor would break position: sticky.
   -------------------------------------------------------------------------- */
html.icge-js [data-reveal] > div > *:not(.svc-stage) {
  opacity: var(--icge-in, 0);
  transform: translate3d(0, calc(var(--icge-rise) * (1 - var(--icge-in, 0))), 0);
  transition:
    opacity   var(--icge-med) var(--icge-ease),
    transform var(--icge-med) var(--icge-ease);
}

/* Heading -> supporting text -> visual, rather than all at once. */
html.icge-js [data-reveal] > div > *:nth-child(1) { transition-delay: calc(var(--icge-step) * 0); }
html.icge-js [data-reveal] > div > *:nth-child(2) { transition-delay: calc(var(--icge-step) * 1); }
html.icge-js [data-reveal] > div > *:nth-child(3) { transition-delay: calc(var(--icge-step) * 2); }
html.icge-js [data-reveal] > div > *:nth-child(4) { transition-delay: calc(var(--icge-step) * 3); }
html.icge-js [data-reveal] > div > *:nth-child(5) { transition-delay: calc(var(--icge-step) * 4); }
html.icge-js [data-reveal] > div > *:nth-child(n + 6) { transition-delay: calc(var(--icge-step) * 5); }

/* Blocks holding imagery or a map take the slower cinematic curve. */
html.icge-js [data-reveal] > div > *:not(.svc-stage):has(image-slot, iframe) {
  transition-duration: var(--icge-slow), var(--icge-slow);
}

/* The Services stage is exempt from the reveal altogether. It is the whole
   services experience in one block, it already carries its own crossfade,
   scale-settle and indicator motion, and it hosts the sticky image frame -
   so animating it here would both double up and risk blanking the section. */

/* --------------------------------------------------------------------------
   4. Editorial image hover - alive, not animated. Pointer devices only.
   -------------------------------------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  html.icge-js .icge-zoom { overflow: hidden; }
  html.icge-js .icge-zoom > image-slot {
    transition: transform 760ms var(--icge-ease);
  }
  html.icge-js .icge-zoom:hover > image-slot { transform: scale(1.03); }
}

/* --------------------------------------------------------------------------
   5. CTA press state. The buttons carry inline hover styles, which win over a
   stylesheet; :active is unclaimed, so this adds a tactile press on mouse and
   touch without altering the existing hover treatment.
   -------------------------------------------------------------------------- */
html.icge-js a[style*="letter-spacing: 0.18em"],
html.icge-js button[style*="letter-spacing: 0.18em"],
html.icge-js .svc-cta {
  transition: transform var(--icge-fast) var(--icge-ease);
  -webkit-tap-highlight-color: transparent;
}
html.icge-js a[style*="letter-spacing: 0.18em"]:active,
html.icge-js button[style*="letter-spacing: 0.18em"]:active,
html.icge-js .svc-cta:active { transform: translateY(1px); }

/* --------------------------------------------------------------------------
   6. Accessibility. Reduced motion means the site arrives instantly and stays
   completely usable - no travel, no scale, no stagger, no page-load fade.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html.icge-js .hero-art-desktop,
  html.icge-js .hero-art-mobile,
  html.icge-js [data-reveal] > div > * {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  html.icge-js .icge-zoom:hover > image-slot { transform: none !important; }
  html.icge-js *,
  html.icge-js *::before,
  html.icge-js *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* The floating WhatsApp button is deliberately static - never animated. */
html.icge-js .wa-fab,
html.icge-js .wa-fab:hover {
  animation: none !important;
  transform: none !important;
}
