/* ==========================================================================
   Motion — the layer that separates "clean" from "expensive".

   Rules this file follows:
   · transform and opacity only, so everything stays on the compositor
   · every effect is motivated by the content, never decorative
   · one-way: nothing re-animates on scroll up
   · the whole file collapses under prefers-reduced-motion at the bottom
   ========================================================================== */

/* --------------------------------------------------------------------------
   Masked title reveal

   The headline rises from behind its own edge rather than fading in. This is
   the single highest-value move on the page: a fade reads as a web page, a
   mask reads as a title card.

   The clip needs breathing room or descenders and accents get sliced — hence
   the padding/negative-margin pair, which enlarges the clip box without
   changing layout.
   -------------------------------------------------------------------------- */

.js-reveal .reveal-mask {
  overflow: clip;
  padding-bottom: 0.18em;
  margin-bottom: -0.18em;
}

.js-reveal .reveal-mask > span {
  display: block;
  transform: translate3d(0, 110%, 0);
  transition: transform 0.95s var(--ease-out);
}

.js-reveal .reveal-mask.is-visible > span {
  transform: none;
}

/* --------------------------------------------------------------------------
   Process timeline — the rule draws itself, then the marker lands

   Section 02 is the site's central argument, so it is the one place worth
   animating structurally rather than just fading in. Each step's rule wipes
   from the left in sequence, so the eye reads the chain in order.
   -------------------------------------------------------------------------- */

.step {
  border-top: 0; /* replaced by the animatable rule below */
}

.step::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 1px;
  background-color: var(--section-rule);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

.js-reveal .step::after {
  transition: transform 0.8s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 90ms);
}

.step.is-visible::after,
html:not(.js-reveal) .step::after {
  transform: scaleX(1);
}

/* The dot arrives after its rule, so it reads as landing on the line. */
.js-reveal .step::before {
  transform: scale(0);
  transition: transform 0.45s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 90ms + 320ms);
}

.js-reveal .step.is-visible::before {
  transform: scale(1);
}

/* --------------------------------------------------------------------------
   Counters

   Numerals are held at a fixed width while counting so the row does not
   twitch as digits change — the single detail that makes an animated figure
   look engineered rather than gimmicky.
   -------------------------------------------------------------------------- */

.stat__value {
  font-variant-numeric: tabular-nums lining-nums;
}

/* --------------------------------------------------------------------------
   Card interaction
   -------------------------------------------------------------------------- */

.method,
.solution {
  transition:
    transform 0.45s var(--ease-out),
    border-color 0.45s var(--ease-out),
    box-shadow 0.45s var(--ease-out);
}

.method:hover,
.solution:hover {
  transform: translateY(-3px);
  border-color: rgb(192 118 74 / 0.5);
  box-shadow: 0 18px 40px -24px rgb(16 13 13 / 0.35);
}

.method__icon {
  transition: transform 0.5s var(--ease-out);
}

.method:hover .method__icon {
  transform: translateY(-2px) scale(1.04);
}

.domain {
  transition:
    transform 0.45s var(--ease-out),
    border-color 0.45s var(--ease-out);
}

.domain:hover {
  transform: translateY(-3px);
  border-color: rgb(192 118 74 / 0.45);
}

.domain__title {
  transition: color 0.35s var(--ease-out);
}

.domain:hover .domain__title {
  color: var(--color-accent);
}

/* Placeholder tiles breathe on hover too, so the section does not read as
   dead space while the real case studies are pending. */
.project {
  transition: border-color 0.4s var(--ease-out), transform 0.4s var(--ease-out);
}

.project:hover {
  transform: translateY(-2px);
  border-color: rgb(192 118 74 / 0.45);
}

/* --------------------------------------------------------------------------
   Buttons — the arrow is the affordance, so it moves, not the whole control
   -------------------------------------------------------------------------- */

.btn--primary::after,
.btn--solid::after {
  content: "→";
  margin-inline-start: 0.55em;
  transition: transform 0.35s var(--ease-out);
}

.btn--primary:hover::after,
.btn--primary:focus-visible::after,
.btn--solid:hover::after,
.btn--solid:focus-visible::after {
  transform: translateX(4px);
}

/* --------------------------------------------------------------------------
   Active section indicator

   The nav rule already grows on hover; scroll-spy reuses the same mark so the
   menu shows where you are without inventing a second visual language.
   -------------------------------------------------------------------------- */

.header__link[data-active="true"] {
  opacity: 1;
}

.header__link[data-active="true"]::after {
  transform: scaleX(1);
  background-color: var(--color-accent);
}

/* --------------------------------------------------------------------------
   Anchor navigation
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/* ==========================================================================
   Reduced motion — everything above collapses to its finished state.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .js-reveal .reveal-mask > span,
  .js-reveal .step::after,
  .js-reveal .step::before {
    transform: none;
    transition: none;
  }

  .js-reveal .step::after {
    transform: scaleX(1);
  }

  .method,
  .solution,
  .domain,
  .project,
  .method__icon,
  .domain__media img,
  .btn--primary::after,
  .btn--solid::after {
    transition: none;
  }

  .method:hover,
  .solution:hover,
  .domain:hover,
  .project:hover {
    transform: none;
  }
}
