/* =============================================================================
   17. JS-DRIVEN INTERACTIONS
   Progressive-enhancement hooks toggled by js/main.js. Nothing here is load
   bearing for content — every element is fully visible and usable with
   script disabled; these classes only add polish on top.
   ============================================================================= */
/* Loads LAST. Progressive-enhancement classes toggled by js/main.js (.reveal, .is-visible, .is-active, .site-header--scrolled, .back-to-top, .btn__ripple). Depends on: tokens.css and every component/section file above (some rules deliberately override a component's own transition list). */

/* --- Sticky header: transition property lives here (not in section 9) so
       the base rule's appearance is untouched until scroll actually adds
       the modifier class below. --- */
.site-header {
  transition: background var(--transition-panel), border-color var(--transition-panel),
    box-shadow var(--transition-panel), backdrop-filter var(--transition-panel),
    transform 0.2s var(--ease-out-expo);
}

.site-header--scrolled {
  background: color-mix(in oklch, var(--color-glass-strong), transparent 8%);
  border-color: color-mix(in oklch, var(--color-border), transparent 8%);
  backdrop-filter: blur(20px) saturate(150%);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
  box-shadow: var(--shadow-menu), 0 1px 0 oklch(100% 0 0 / 0.28) inset;
}

:root[data-theme="dark"] .site-header--scrolled {
  background: color-mix(in oklch, var(--color-bg-card), transparent 6%);
  border-color: color-mix(in oklch, var(--color-glow), transparent 70%);
  backdrop-filter: blur(22px) saturate(155%);
  -webkit-backdrop-filter: blur(22px) saturate(155%);
  box-shadow: var(--shadow-menu), 0 1px 0 oklch(100% 0 0 / 0.08) inset;
}

/* --- Active nav link: matches the existing hover treatment ---------------- */
.site-header__links a.is-active,
.mobile-menu-panel a.is-active {
  color: var(--color-accent-strong);
}

/* --- Scroll reveal ----------------------------------------------------------
   `.reveal` only ever sets the opacity VALUE, never `transition` itself.
   Simple targets (section intros) get their transition declared alongside
   it below. Workflow cards and services nodes already declare a combined
   transition list on their own base rule (opacity + hover transform/glow)
   — letting `.reveal` redeclare `transition` there would replace that list
   wholesale and silently break the hover animation once revealed. */
.reveal {
  opacity: 0;
}

.reveal.is-visible {
  opacity: 1;
}

/* Section intros never carry their own transition, so they get the fuller
   opacity + translateY treatment declared directly here. */
.section-intro.reveal {
  transform: translateY(20px);
  transition: opacity 0.7s var(--ease-out-expo), transform 0.7s var(--ease-out-expo);
}

.section-intro.reveal.is-visible {
  transform: translateY(0);
}

/* Larger visual blocks use the same quiet fade-up, while their existing
   hover/tilt transforms remain on their own nested elements. */
.platform__panel.reveal,
.carousel__tilt.reveal,
.site-footer__closing.reveal {
  transform: translateY(18px);
  transition: opacity 0.65s var(--ease-out-expo), transform 0.65s var(--ease-out-expo);
}

.platform__panel.reveal.is-visible,
.carousel__tilt.reveal.is-visible,
.site-footer__closing.reveal.is-visible {
  transform: translateY(0);
}

/* Workflow cards: stagger by DOM position. Each card is now wrapped in a
   .workflow__card-tilt (see effects.css/index.html) so IT — not the card
   itself — sits at position 1/3/5/7 among the connector elements between
   them; the card's own reveal delay is set via that wrapper's position.
   The explicit 0s reset (2-class specificity) is required so the generic
   --reveal-index rule below — same specificity, but loads later — doesn't
   win the cascade tie and hand "Observe" a stray multi-section-wide index
   delay of its own. */
.workflow__card.reveal { transition-delay: 0s; }
.workflow__card-tilt:nth-child(3) .workflow__card.reveal { transition-delay: 0.1s; }
.workflow__card-tilt:nth-child(5) .workflow__card.reveal { transition-delay: 0.2s; }
.workflow__card-tilt:nth-child(7) .workflow__card.reveal { transition-delay: 0.3s; }

/* Services nodes: stagger by the same --node-index used for their float
   animation delay, so reveal order matches the diagram's visual reading
   order. --node-index is set on .services__node-position and inherits
   straight through the .services__node-tilt wrapper in between. */
.services__node.reveal {
  transition-delay: calc(var(--node-index, 0) * 0.08s);
}

/* --- Generalized reveal stagger ---------------------------------------------
   js/main.js sets --reveal-index (the element's position within the whole
   reveal target list) on every .reveal element before observing it. This
   only affects elements that don't already declare their own delay above —
   those rules are more specific (two classes) and always win regardless of
   load order. */
.reveal {
  transition-delay: calc(var(--reveal-index, 0) * 0.08s);
}

/* --- Reveal flavor: materialize (blur-in) -----------------------------------
   Filter-based, so it's safe to combine with any element regardless of what
   transform it already owns elsewhere. Applied to section intros only (see
   index.html) — redeclares the full transition list from the base
   .section-intro.reveal rule above so adding `filter` here doesn't clobber
   the existing opacity/transform transition. */
.section-intro.reveal.reveal--materialize {
  filter: blur(6px);
  transition: opacity 0.7s var(--ease-out-expo), transform 0.7s var(--ease-out-expo),
    filter 0.7s var(--ease-out-expo);
}

.section-intro.reveal.reveal--materialize.is-visible {
  filter: blur(0);
}

/* --- Back to top: fixed bottom-left, mirrors the AI assistant's
       bottom-right position; revealed by JS past a scroll threshold ------- */
.back-to-top {
  position: fixed;
  left: var(--space-6);
  bottom: var(--space-6);
  z-index: var(--z-assistant);
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--color-accent-strong), var(--color-accent) 55%, var(--color-glow-strong));
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border: 1px solid color-mix(in oklch, var(--color-accent), white 18%);
  box-shadow: 0 10px 24px color-mix(in oklch, var(--color-accent), transparent 65%), 0 1px 0 oklch(100% 0 0 / 0.3) inset;
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: opacity var(--transition-slow), transform var(--transition-slow),
    visibility var(--transition-slow), background-position 0.45s var(--ease-out-expo), box-shadow var(--transition-slow);
  background-size: 150% 150%;
}

.back-to-top.is-visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.back-to-top:hover {
  background-position: 100% 50%;
  transform: translateY(-3px);
  box-shadow: 0 16px 30px color-mix(in oklch, var(--color-accent), transparent 52%), 0 1px 0 oklch(100% 0 0 / 0.35) inset;
}

.back-to-top:focus-visible {
  outline: 2px solid var(--color-accent-strong);
  outline-offset: 3px;
}

:root[data-theme="dark"] .back-to-top {
  color: var(--color-text-on-accent);
  border-color: color-mix(in oklch, var(--color-glow), white 14%);
  box-shadow: 0 10px 24px oklch(56% 0.19 278 / 0.28), 0 0 16px oklch(68% 0.18 215 / 0.1),
    0 1px 0 oklch(100% 0 0 / 0.3) inset;
}

:root[data-theme="dark"] .back-to-top:hover {
  box-shadow: 0 16px 30px oklch(56% 0.19 278 / 0.36), 0 0 22px oklch(68% 0.18 215 / 0.15),
    0 1px 0 oklch(100% 0 0 / 0.36) inset;
}

:root[data-theme="dark"] .back-to-top:focus-visible {
  outline-color: var(--color-glow);
}

@media (max-width: 480px) {
  .back-to-top {
    left: var(--space-4);
    bottom: var(--space-4);
    width: 44px;
    height: 44px;
  }
}

/* --- Button ripple: click-position expanding circle, primary/secondary
       buttons only (a text `.btn--link` has no filled surface to ripple
       against). Skipped entirely by JS under prefers-reduced-motion. ----- */
.btn {
  position: relative;
  overflow: hidden;
}

.btn__ripple {
  position: absolute;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.22;
  transform: scale(0);
  pointer-events: none;
  animation: btn-ripple 0.6s ease-out;
}

@keyframes btn-ripple {
  to {
    transform: scale(1);
    opacity: 0;
  }
}
