/* ===========================================================================
   motion.css — styles for the motion layer (driven by assets/js/motion.js)
   ===========================================================================
   Every initial state is enabled only by the `.has-js` class on <html>.
   Without JavaScript everything is visible and static — a rule, not an option.
   =========================================================================== */

/* ---------------------------------------------------------------------------
   1. Staggered reveal
--------------------------------------------------------------------------- */
.has-js .stagger-item {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--duration-slow) var(--ease-out),
    transform var(--duration-slow) var(--ease-out);
}

.has-js .stagger-item.is-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .has-js .stagger-item {
    opacity: 1;
    transform: none;
  }

}

/* ---------------------------------------------------------------------------
   2. Reading progress bar — a thin line under the navigation
--------------------------------------------------------------------------- */
.scroll-progress {
  position: absolute;
  bottom: -1px;
  left: 0;
  width: 100%;
  height: 2px;
  transform: scaleX(0);
  transform-origin: left center;
  background: linear-gradient(
    to right,
    var(--color-accent),
    var(--color-accent-hover)
  );
  will-change: transform;
  pointer-events: none;
}

/* ---------------------------------------------------------------------------
   3. Audio waveform in the call card
--------------------------------------------------------------------------- */
.wave {
  display: block;
  width: 100%;
  height: 44px;
}

/* ---------------------------------------------------------------------------
   3b. Hero choreography and ambient technical grid
--------------------------------------------------------------------------- */
.has-js [data-hero-sequence] .hero__text > * {
  animation: hero-enter 720ms var(--ease-out) both;
}

.has-js [data-hero-sequence] .hero__text > :nth-child(2) { animation-delay: 90ms; }
.has-js [data-hero-sequence] .hero__text > :nth-child(3) { animation-delay: 170ms; }
.has-js [data-hero-sequence] .hero__text > :nth-child(4) { animation-delay: 250ms; }
.has-js [data-hero-sequence] .hero__text > :nth-child(5) { animation-delay: 340ms; }

.has-js .hero .grid-backdrop {
  animation: grid-drift 22s linear infinite;
}

.has-js .hero .accent-glow {
  animation: glow-breathe 7s var(--ease-in-out) infinite alternate;
}

@keyframes hero-enter {
  from { opacity: 0; transform: translateY(22px); }
  to { opacity: 1; transform: none; }
}

@keyframes grid-drift {
  to { background-position: 72px 36px; }
}

@keyframes glow-breathe {
  from { opacity: 0.65; transform: scale(0.96); }
  to { opacity: 1; transform: scale(1.05); }
}

/* Fields light up in the same order in which the spoken sentence becomes a
   structured case. They stay readable throughout the cycle. */
.has-js .proof__card.is-running .datafield {
  animation: proof-field-cycle 6.4s var(--ease-out) infinite;
}

.has-js .proof__card.is-running .datafield:nth-child(1) { animation-delay: 0.9s; }
.has-js .proof__card.is-running .datafield:nth-child(2) { animation-delay: 1.25s; }
.has-js .proof__card.is-running .datafield:nth-child(3) { animation-delay: 1.6s; }
.has-js .proof__card.is-running .datafield:nth-child(4) { animation-delay: 1.95s; }

.has-js .proof__card.is-running .proof__result {
  animation: proof-result-cycle 6.4s var(--ease-out) 2.55s infinite;
}

.has-js .proof__card.is-running .proof__arrow::before,
.has-js .proof__card.is-running .proof__arrow::after {
  animation: proof-line-cycle 6.4s var(--ease-out) infinite;
  transform-origin: center;
}

@keyframes proof-field-cycle {
  0%, 9%, 25%, 100% { transform: none; box-shadow: none; }
  13%, 20% {
    transform: translateX(var(--space-1));
    box-shadow: inset var(--space-1) 0 0 var(--color-accent), 0 0 0 1px var(--color-accent-border);
  }
}

@keyframes proof-result-cycle {
  0%, 10%, 30%, 100% { transform: none; opacity: 1; }
  16% { transform: translateY(-3px); opacity: 0.72; }
  21% { transform: none; opacity: 1; }
}

@keyframes proof-line-cycle {
  0%, 6% { transform: scaleX(0.15); opacity: 0.25; }
  18%, 45% { transform: scaleX(1); opacity: 1; }
  60%, 100% { transform: scaleX(0.35); opacity: 0.45; }
}

/* ---------------------------------------------------------------------------
   4. Edge glow following the cursor
   ---------------------------------------------------------------------------
   Implemented with a pseudo-element to avoid adding nodes to the DOM.
   The 50%/50% default keeps anything from jumping before the first mouse move.
--------------------------------------------------------------------------- */
[data-glow] {
  --glow-x: 50%;
  --glow-y: 50%;
  position: relative;
  isolation: isolate;
}

[data-glow]::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-out);
  background: radial-gradient(
    380px circle at var(--glow-x) var(--glow-y),
    var(--color-accent-quiet),
    transparent 62%
  );
  pointer-events: none;
  z-index: -1;
}

[data-glow]:hover::before {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  [data-glow]::before {
    display: none;
  }

}

/* ---------------------------------------------------------------------------
   5. Line under a section heading, drawn when it scrolls into view
--------------------------------------------------------------------------- */
.section-marker {
  position: relative;
}

.section-marker::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 1px;
  width: 100%;
  background-color: var(--color-accent-border);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--duration-deliberate) var(--ease-out);
}

/* Tabs change as one coherent panel instead of flashing between display:none
   states. */
.has-js .panels__body:not([hidden]) {
  animation: panel-enter var(--duration-slow) var(--ease-out) both;
}

@keyframes panel-enter {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: none; }
}

.has-js .section-marker.is-visible::after,
.section-marker.is-visible::after {
  transform: scaleX(1);
}

@media (prefers-reduced-motion: reduce) {
  .section-marker::after {
    transform: scaleX(1);
  }

}

/* ---------------------------------------------------------------------------
   6. Shine sweep on the primary call to action
   ---------------------------------------------------------------------------
   A single pass of light on hover — a "this is the action" cue, without an
   infinite loop that tires the eye.
--------------------------------------------------------------------------- */
.btn--primary {
  position: relative;
  overflow: hidden;
}

.btn--primary::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-120%);
  background: linear-gradient(
    100deg,
    transparent 20%,
    rgb(255 255 255 / 22%) 50%,
    transparent 80%
  );
  pointer-events: none;
}

.btn--primary:hover::after {
  transform: translateX(120%);
  transition: transform var(--duration-deliberate) var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
  .btn--primary::after {
    display: none;
  }

}

/* ---------------------------------------------------------------------------
   7. Highlighted figures
--------------------------------------------------------------------------- */
.stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.stat__value {
  font-family: var(--font-display);
  font-size: var(--text-display-md);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  color: var(--color-accent-text);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.stat__label {
  font-size: var(--text-caption);
  line-height: var(--leading-normal);
  color: var(--color-text-muted);
}

/* ---------------------------------------------------------------------------
   PRINT — nothing may depend on having scrolled
   ---------------------------------------------------------------------------
   Reveal-on-scroll hides content until an IntersectionObserver fires. That is
   fine in a browser, where the reader scrolls, but a print or PDF export never
   scrolls: whatever had not yet been revealed would come out as blank space.
   The same applies to any tool that renders the page without scrolling it.

   So print forces every animated state to its final value. Decorative layers go
   as well — a grid backdrop and a glow cost ink and add nothing on paper.
--------------------------------------------------------------------------- */
@media print {
  .has-js .reveal,
  .has-js .reveal.is-visible,
  .has-js .stagger-item,
  .has-js .stagger-item.is-in {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .section-marker::after {
    transform: scaleX(1) !important;
  }

  .grid-backdrop,
  .accent-glow,
  .scroll-progress,
  [data-glow]::before,
  .btn--primary::after {
    display: none !important;
  }

}

/* ===========================================================================
   RYSOWANIE POŁĄCZEŃ NA DIAGRAMIE
   ===========================================================================
   The spokes of the module diagram draw outward from the register when the
   drawing scrolls into view. This is the one animation on the site that says
   something: it shows the DIRECTION of the connection, which is the claim the
   section makes. Everything else here is a fade.

   `pathLength="1"` is set on the paths so dash values are a fraction of the
   line rather than user units — without it every spoke would need its own
   measured length and the four would finish at different moments.

   The animation only runs once `.is-visible` lands, so a spoke never draws
   while off screen and the reader always catches it.
   =========================================================================== */
.has-js .illus--iso .illus__spoke {
  stroke-dasharray: 0.06 0.05;
  stroke-dashoffset: 1;
  opacity: 0;
}

.has-js .reveal.is-visible .illus--iso .illus__spoke {
  animation: spoke-draw 900ms cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
}

/* Stagger the four so the eye follows one at a time instead of seeing a flash. */
.has-js .reveal.is-visible .illus--iso .illus__spoke:nth-of-type(2) { animation-delay: 110ms; }
.has-js .reveal.is-visible .illus--iso .illus__spoke:nth-of-type(3) { animation-delay: 220ms; }
.has-js .reveal.is-visible .illus--iso .illus__spoke:nth-of-type(4) { animation-delay: 330ms; }

@keyframes spoke-draw {
  from { stroke-dashoffset: 1; opacity: 0; }
  20%  { opacity: 1; }
  to   { stroke-dashoffset: 0; opacity: 1; }
}

/* Numbered nodes arrive after their spoke reaches them. */
.has-js .illus--iso .illus__node,
.has-js .illus--iso .illus__label--mid {
  opacity: 0;
}

.has-js .reveal.is-visible .illus--iso .illus__node,
.has-js .reveal.is-visible .illus--iso .illus__label--mid {
  animation: node-in 420ms ease-out 640ms forwards;
}

@keyframes node-in {
  from { opacity: 0; transform: scale(0.85); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .has-js .illus--iso .illus__spoke,
  .has-js .illus--iso .illus__node,
  .has-js .illus--iso .illus__label--mid {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
    opacity: 1;
    animation: none;
  }
}

/* ===========================================================================
   TECHNICAL SCENES — drawn once, then gently react while in view
   =========================================================================== */
.has-js .illus__panel--motion.reveal .illus__key:not(.integration-scene__link, .integration-scene__arrow) {
  stroke-dasharray: 600;
  stroke-dashoffset: 600;
}

.has-js .illus__panel--motion.reveal.is-visible .illus__key:not(.integration-scene__link, .integration-scene__arrow) {
  animation: scene-draw 1.35s var(--ease-out) forwards;
}

.has-js .integration-scene__link,
.has-js .integration-scene__arrow,
.has-js .integration-scene__label {
  opacity: 0;
}

.has-js .illus__panel--motion.is-active .integration-scene__link {
  animation: integration-link 2.2s var(--ease-in-out) 900ms infinite;
}

.has-js .illus__panel--motion.is-active .integration-scene__arrow,
.has-js .illus__panel--motion.is-active .integration-scene__label {
  animation: integration-arrive 2.2s var(--ease-out) 1.25s infinite;
}

.has-js .secure-scene__lock {
  transform-box: fill-box;
  transform-origin: center bottom;
}

.has-js .illus__panel--motion.is-active .secure-scene__lock {
  animation: secure-lock 3.6s var(--ease-spring) infinite;
}

.has-js .illus__panel--motion.is-active .secure-scene__lock--two { animation-delay: 240ms; }
.has-js .illus__panel--motion.is-active .secure-scene__lock--three { animation-delay: 480ms; }

.has-js .cta-panel.is-visible .cta-orbit {
  animation: orbit-turn 18s linear infinite;
}

.has-js .cta-panel.is-visible .cta-orbit span {
  animation: orbit-node 2.4s var(--ease-in-out) infinite alternate;
}

.has-js .cta-panel.is-visible .cta-orbit span:nth-child(2) { animation-delay: 400ms; }
.has-js .cta-panel.is-visible .cta-orbit span:nth-child(3) { animation-delay: 800ms; }

@keyframes scene-draw {
  to { stroke-dashoffset: 0; }
}

@keyframes integration-link {
  0% { stroke-dashoffset: 32; opacity: 0.25; }
  35%, 70% { opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 0.25; }
}

@keyframes integration-arrive {
  0%, 18% { opacity: 0; transform: translateX(-6px); }
  35%, 70% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateX(5px); }
}

@keyframes secure-lock {
  0%, 15%, 100% { transform: none; }
  7% { transform: translateY(-5px) scale(1.04); }
}

@keyframes orbit-turn {
  to { transform: translateY(-50%) rotate(360deg); }
}

@keyframes orbit-node {
  to { box-shadow: 0 0 0 var(--space-3) var(--color-accent-quiet); }
}

@media (prefers-reduced-motion: reduce) {
  .has-js [data-hero-sequence] .hero__text > *,
  .has-js .hero .grid-backdrop,
  .has-js .hero .accent-glow,
  .has-js .proof__card .datafield,
  .has-js .proof__card .proof__result,
  .has-js .proof__card .proof__arrow::before,
  .has-js .proof__card .proof__arrow::after,
  .has-js .panels__body:not([hidden]),
  .has-js .illus__panel--motion .illus__key,
  .has-js .integration-scene__link,
  .has-js .integration-scene__arrow,
  .has-js .integration-scene__label,
  .has-js .secure-scene__lock,
  .has-js .cta-panel .cta-orbit,
  .has-js .cta-panel .cta-orbit span {
    animation: none;
    opacity: 1;
    transform: none;
    stroke-dasharray: none;
    stroke-dashoffset: 0;
  }

  .has-js .cta-panel .cta-orbit {
    transform: translateY(-50%);
  }
}

/* ===========================================================================
   CASE FLOW — the moving details inside the currently explained step
   ===========================================================================
   The loop itself is controlled by motion.js so it can pause off-screen. CSS
   only draws the tiny local action: a ringing phone, extracted fields, a
   notification and the technician's last few steps toward the building.
   =========================================================================== */
.has-js .caseflow.is-running .caseflow__step.is-active .caseflow__phone {
  transform-box: fill-box;
  transform-origin: center;
  animation: caseflow-phone 680ms var(--ease-in-out) 2;
}

.has-js .caseflow.is-running .caseflow__step.is-active .caseflow__ring {
  stroke-dasharray: 28;
  stroke-dashoffset: 28;
  animation: caseflow-ring 900ms var(--ease-out) infinite;
}

.has-js .caseflow.is-running .caseflow__step.is-active .caseflow__ring--two {
  animation-delay: 160ms;
}

.has-js .caseflow.is-running .caseflow__step.is-active .caseflow__data-line {
  stroke-dasharray: 72;
  stroke-dashoffset: 72;
  animation: caseflow-write 720ms var(--ease-out) forwards;
}

.has-js .caseflow.is-running .caseflow__step.is-active .caseflow__data-line--two {
  animation-delay: 220ms;
}

.has-js .caseflow.is-running .caseflow__step.is-active .caseflow__data-line--three {
  animation-delay: 440ms;
}

.has-js .caseflow.is-running .caseflow__step.is-active .caseflow__notification {
  transform-box: fill-box;
  transform-origin: top center;
  animation: caseflow-bell 680ms var(--ease-in-out) 2;
}

.has-js .caseflow.is-running .caseflow__step.is-active .caseflow__ping {
  transform-box: fill-box;
  transform-origin: center;
  animation: caseflow-ping 1.2s var(--ease-out) infinite;
}

.has-js .caseflow.is-running .caseflow__step.is-active .caseflow__ping--two {
  animation-delay: 220ms;
}

.has-js .caseflow.is-running .caseflow__step.is-active .caseflow__technician {
  animation: caseflow-arrive 1.25s var(--ease-out) forwards;
}

.has-js .caseflow.is-running .caseflow__step.is-active .caseflow__arrival {
  stroke-dasharray: 24;
  stroke-dashoffset: 24;
  animation: caseflow-write 900ms var(--ease-out) forwards;
}

@keyframes caseflow-phone {
  0%, 100% { transform: rotate(0); }
  30% { transform: rotate(-4deg); }
  70% { transform: rotate(4deg); }
}

@keyframes caseflow-ring {
  0% { stroke-dashoffset: 28; opacity: 0; }
  25% { opacity: 1; }
  75%, 100% { stroke-dashoffset: 0; opacity: 0; }
}

@keyframes caseflow-write {
  from { stroke-dashoffset: 72; opacity: 0.35; }
  to { stroke-dashoffset: 0; opacity: 1; }
}

@keyframes caseflow-bell {
  0%, 100% { transform: rotate(0); }
  30% { transform: rotate(-7deg); }
  70% { transform: rotate(7deg); }
}

@keyframes caseflow-ping {
  from { transform: scale(0.5); opacity: 0.8; }
  to { transform: scale(1.18); opacity: 0; }
}

@keyframes caseflow-arrive {
  from { transform: translateX(-12px); opacity: 0.45; }
  to { transform: translateX(0); opacity: 1; }
}

/* Product flow: the filled rail follows the section through the viewport and
   the active card comes forward just enough to keep a seven-step diagram easy
   to scan. */
.flow--animated .flow__spine::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, var(--color-accent), var(--color-accent-text));
  transform: scaleY(var(--flow-progress, 0));
  transform-origin: top center;
  transition: transform 520ms var(--ease-out);
}

.has-js .flow--animated .flow__card,
.has-js .flow--animated .flow__dot {
  transition: border-color var(--duration-base) var(--ease-out),
    background-color var(--duration-base) var(--ease-out),
    box-shadow var(--duration-base) var(--ease-out),
    transform var(--duration-base) var(--ease-out),
    opacity var(--duration-base) var(--ease-out);
}

.has-js .flow--animated .flow__node:not(.is-current):not(.is-past) .flow__card {
  opacity: 0.55;
}

.has-js .flow--animated .flow__node.is-current .flow__card {
  border-color: var(--color-accent-border);
  box-shadow: var(--shadow-md);
  transform: translateX(var(--space-2));
}

.has-js .flow--animated .flow__node.is-current .flow__dot,
.has-js .flow--animated .flow__node.is-past .flow__dot {
  color: var(--color-text-on-accent);
  background-color: var(--color-accent);
  border-color: var(--color-accent);
}

.has-js .flow--animated .flow__node.is-current .flow__art .illus__key {
  stroke-dasharray: 160;
  animation: service-flow-draw 900ms var(--ease-out) both;
}

@keyframes service-flow-draw {
  from { stroke-dashoffset: 160; opacity: 0.35; }
  to { stroke-dashoffset: 0; opacity: 1; }
}

/* The dashboard wakes up in a deliberate order: status first, then the work
   queue and finally the reports. This mirrors how an administrator reads it. */
.has-js .ops-center .ops-kpi,
.has-js .ops-center .ops-board,
.has-js .ops-center .ops-activity,
.has-js .ops-center .ops-chart,
.has-js .ops-center .ops-actions {
  opacity: 0;
  transform: translateY(var(--space-3));
  transition: opacity 520ms var(--ease-out), transform 520ms var(--ease-out);
}

.has-js .ops-center.is-live .ops-kpi,
.has-js .ops-center.is-live .ops-board,
.has-js .ops-center.is-live .ops-activity,
.has-js .ops-center.is-live .ops-chart,
.has-js .ops-center.is-live .ops-actions {
  opacity: 1;
  transform: translateY(0);
}

.has-js .ops-center.is-live .ops-kpi:nth-child(2) { transition-delay: 70ms; }
.has-js .ops-center.is-live .ops-kpi:nth-child(3) { transition-delay: 140ms; }
.has-js .ops-center.is-live .ops-kpi:nth-child(4) { transition-delay: 210ms; }
.has-js .ops-center.is-live .ops-board { transition-delay: 260ms; }
.has-js .ops-center.is-live .ops-activity { transition-delay: 340ms; }
.has-js .ops-center.is-live .ops-chart { transition-delay: 410ms; }
.has-js .ops-center.is-live .ops-actions { transition-delay: 480ms; }

.has-js .ops-center .ops-bars i::after {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 900ms var(--ease-out) 620ms;
}

.has-js .ops-center.is-live .ops-bars i::after {
  transform: scaleX(1);
}

.has-js .ops-center.is-live .ops-ticket--urgent {
  animation: ops-urgent 2.8s var(--ease-in-out) 1 900ms;
}

.has-js .ops-center.is-live .ops-feed li:first-child .ops-feed__dot {
  animation: ops-live-dot 1.8s var(--ease-out) infinite;
}

@keyframes ops-urgent {
  0%, 100% { background-color: transparent; }
  45% { background-color: var(--color-warn-quiet); }
}

@keyframes ops-live-dot {
  0% { box-shadow: 0 0 0 1px var(--color-accent-border); }
  70%, 100% { box-shadow: 0 0 0 0.45rem transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .has-js .caseflow .caseflow__phone,
  .has-js .caseflow .caseflow__ring,
  .has-js .caseflow .caseflow__data-line,
  .has-js .caseflow .caseflow__notification,
  .has-js .caseflow .caseflow__ping,
  .has-js .caseflow .caseflow__technician,
  .has-js .caseflow .caseflow__arrival {
    animation: none;
    transform: none;
    stroke-dasharray: none;
    stroke-dashoffset: 0;
    opacity: 1;
  }

  .has-js .flow--animated .flow__card,
  .has-js .flow--animated .flow__dot,
  .has-js .ops-center .ops-kpi,
  .has-js .ops-center .ops-board,
  .has-js .ops-center .ops-activity,
  .has-js .ops-center .ops-chart,
  .has-js .ops-center .ops-actions,
  .has-js .ops-center .ops-bars i::after,
  .has-js .ops-center .ops-ticket--urgent,
  .has-js .ops-center .ops-feed__dot {
    animation: none;
    opacity: 1;
    transform: none;
    transition: none;
  }
}

@media print {
  .caseflow__step::after {
    transform: scaleX(1) !important;
  }
}
