/* ==========================================================================
   Смарт Решения — Design System · Motion
   --------------------------------------------------------------------------
   The animation layer. Three tiers, deliberately separated:

     1. REVEAL     — blocks entering the viewport once, on scroll.
     2. AMBIENT    — slow, endless background motion (aurora, scan lines).
     3. RESPONSE   — hover / focus / press feedback, owned by components.css.

   Everything here degrades to "already visible, no movement" when the user
   asks for reduced motion, and to "already visible" when JS never runs.
   ========================================================================== */

/* ============================================================ 1. REVEAL ==
   Markup contract:
     <div data-reveal>…</div>                  → rise + fade
     <div data-reveal="fade">…</div>            → fade only
     <div data-reveal="left|right">…</div>      → slide in from the side
     <div data-reveal="scale">…</div>           → settle in from 97%
     <div data-reveal="clip">…</div>            → wipe up under its own edge
     <div data-reveal-group>…</div>             → stagger direct children
     <div data-reveal style="--reveal-i:3">     → manual stagger index

   site.js adds [data-revealed] once the element crosses the viewport. The
   `.js-reveal` class on <html> is what arms the hidden state, so a no-JS or
   failed-script page renders fully visible instead of blank.
   ========================================================================== */

.js-reveal [data-reveal] {
  opacity: 0;
  transition:
    opacity var(--dur-reveal) var(--ease-entrance),
    transform var(--dur-reveal) var(--ease-entrance),
    clip-path var(--dur-reveal) var(--ease-entrance);
  transition-delay: calc(var(--reveal-i, 0) * var(--reveal-stagger));
  will-change: opacity, transform;
}

.js-reveal [data-reveal=''],
.js-reveal [data-reveal='up'] { transform: translate3d(0, var(--reveal-distance), 0); }
.js-reveal [data-reveal='down'] { transform: translate3d(0, calc(-1 * var(--reveal-distance)), 0); }
/* NOTE: the horizontal variants start displaced sideways, so their container
   must clip (`overflow: clip`) whenever the element can sit on a page edge —
   otherwise the pre-reveal offset widens the document. Prefer `up`/`fade` for
   full-bleed blocks. */
.js-reveal [data-reveal='left'] { transform: translate3d(calc(-1 * var(--reveal-distance)), 0, 0); }
.js-reveal [data-reveal='right'] { transform: translate3d(var(--reveal-distance), 0, 0); }
.js-reveal [data-reveal='fade'] { transform: none; }
.js-reveal [data-reveal='scale'] { transform: scale(.97); }
.js-reveal [data-reveal='clip'] {
  transform: translate3d(0, calc(var(--reveal-distance) * 0.6), 0);
  clip-path: inset(0 0 100% 0);
}

/* Revealed state — one rule wins for every variant. */
.js-reveal [data-reveal][data-revealed] {
  opacity: 1;
  transform: none;
  clip-path: inset(0 0 0 0);
  will-change: auto;
}

/* Group stagger: children inherit an index without hand-written delays. */
[data-reveal-group] > * { --reveal-i: 0; }
[data-reveal-group] > *:nth-child(1) { --reveal-i: 0; }
[data-reveal-group] > *:nth-child(2) { --reveal-i: 1; }
[data-reveal-group] > *:nth-child(3) { --reveal-i: 2; }
[data-reveal-group] > *:nth-child(4) { --reveal-i: 3; }
[data-reveal-group] > *:nth-child(5) { --reveal-i: 4; }
[data-reveal-group] > *:nth-child(6) { --reveal-i: 5; }
[data-reveal-group] > *:nth-child(7) { --reveal-i: 6; }
[data-reveal-group] > *:nth-child(8) { --reveal-i: 7; }

/* A rule that draws itself along its own axis as the block arrives. */
.js-reveal [data-reveal-rule] {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease-out);
  transition-delay: calc(var(--reveal-i, 0) * var(--reveal-stagger));
}
.js-reveal [data-reveal-rule][data-revealed] { transform: scaleX(1); }

/* Headline that lifts word-by-word. site.js wraps each word in a span. */
.js-reveal [data-reveal-words] .sr-word {
  display: inline-block;
  opacity: 0;
  transform: translate3d(0, 0.5em, 0);
  transition: opacity var(--dur-reveal) var(--ease-entrance),
              transform var(--dur-reveal) var(--ease-entrance);
  transition-delay: calc(var(--w, 0) * 55ms);
}
.js-reveal [data-reveal-words][data-revealed] .sr-word {
  opacity: 1;
  transform: none;
}

/* ============================================================ 2. AMBIENT == */

/* The page wash drifts very slowly, so the dark theme never looks like a
   flat plate. 24s, tiny amplitude — felt rather than seen. */
@keyframes sr-aurora-drift {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(-1.5%, 1.5%, 0) scale(1.06); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}
body::before { animation: sr-aurora-drift var(--dur-ambient) var(--ease-inout) infinite; }

/* Hero orbs: two large blurred pools behind the headline. */
.sr-orb {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  filter: blur(8px);
  animation: sr-orb-float 18s var(--ease-inout) infinite;
}
.sr-orb--a {
  top: -12rem; right: -9rem;
  width: min(48rem, 90vw); height: min(48rem, 90vw);
  background: radial-gradient(circle, rgba(78, 107, 224, .30), transparent 62%);
}
.sr-orb--b {
  bottom: -18rem; left: 22%;
  width: min(40rem, 80vw); height: min(40rem, 80vw);
  background: radial-gradient(circle, rgba(28, 51, 153, .24), transparent 62%);
  animation-delay: -7s;
  animation-duration: 23s;
}
:root[data-theme='light'] .sr-orb { opacity: .45; }

@keyframes sr-orb-float {
  0%   { transform: translate3d(0, 0, 0); }
  50%  { transform: translate3d(-3%, 4%, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* A single hairline sweeping down the architecture band — reads as a data
   pass moving through the stack. */
@keyframes sr-scan {
  0%   { transform: translateY(0); opacity: 0; }
  8%   { opacity: 1; }
  92%  { opacity: 1; }
  100% { transform: translateY(var(--scan-dist, 320px)); opacity: 0; }
}
.sr-scan {
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--line-accent), transparent);
  animation: sr-scan 7s var(--ease-inout) infinite;
  pointer-events: none;
}

/* Blinking status dot for "live" markers. */
@keyframes sr-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: .35; transform: scale(.82); }
}
.sr-dot {
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--line-accent);
  animation: sr-pulse 2.4s var(--ease-inout) infinite;
}

/* ============================================================ 3. RESPONSE == */

/* Generic hover lift, for blocks that aren't a component of their own. */
.sr-lift {
  transition: transform var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
}
.sr-lift:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }

/* Editorial row that indents and tints as the pointer passes. */
.sr-hoverrow {
  transition: background-color var(--dur-base) var(--ease-out),
              padding-inline-start var(--dur-base) var(--ease-out);
}
.sr-hoverrow:hover { background: var(--surface-subtle); padding-inline-start: 20px; }
.sr-hoverrow__arrow { transition: transform var(--dur-base) var(--ease-out); }
.sr-hoverrow:hover .sr-hoverrow__arrow { transform: translate(3px, -3px); }

/* Theme crossfade. Scoped to the elements that actually change colour rather
   than `body *`, which forced a style recalc on every node in the old build. */
.sr-section,
.sr-card,
.sr-nav,
.sr-footer,
.sr-cta,
.sr-glass,
.sr-pricing,
.sr-btn,
.sr-badge,
.sr-input,
.sr-textarea,
.sr-select {
  transition-property: background-color, border-color, color, box-shadow, transform;
  transition-duration: var(--dur-base);
  transition-timing-function: var(--ease-out);
}

/* Suppress every transition for one frame while the theme flips, so the
   switch feels instant rather than a slow smear across dozens of nodes. */
.sr-theme-switching * {
  transition: none !important;
  animation-duration: 0s !important;
}

/* ---------------------------------------------------- Reduced motion guard */
@media (prefers-reduced-motion: reduce) {
  .js-reveal [data-reveal],
  .js-reveal [data-reveal-rule],
  .js-reveal [data-reveal-words] .sr-word {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    transition: none !important;
  }
  body::before,
  .sr-orb,
  .sr-scan,
  .sr-dot { animation: none !important; }
  .sr-scan { display: none; }
  .sr-lift:hover,
  .sr-card--interactive:hover,
  .sr-pricing:hover,
  .sr-btn:hover { transform: none; }
  .sr-hoverrow:hover { padding-inline-start: 0; }
}
