/* ==========================================================================
   Motion and video (2026-10-23)
   --------------------------------------------------------------------------
   Kept out of the pages' own inline <style> blocks so it is obvious what can
   be removed wholesale if the site should go back to being still.

   This file deliberately does NOT re-implement what already exists.
   index.html already has a scroll-reveal (.feature-card + .in-view, driven by
   the IntersectionObserver at the bottom of that file) and an animated
   .badge-dot. Adding a second reveal system alongside them would be two sets
   of rules to keep in step, so this extends the existing convention instead:
   anything that should fade in gets .in-view applied to it by that same
   observer.

   Uses only variables the pages actually define (--bg-card, --brand,
   --brand-text, --text-secondary, --success, --ink). Note that --ink-body
   and --ink-soft exist in site.css but NOT in index.html's inline :root, so
   they are avoided here - this file is linked from both.

   Nothing below animates a layout property. Only transform and opacity, so
   none of it causes reflow while scrolling.
   ========================================================================== */

/* ---------- Reveal, for elements that are not .feature-card ---------- */
/* Same two-state shape as the existing .feature-card rule, so one observer
   drives both and they move identically. */
.fade-up {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 0.6s ease,
    transform 0.6s ease;
}

.fade-up.in-view {
  opacity: 1;
  transform: none;
}

/* ---------- Ambient ---------- */
/* The hero glow already existed as a static radial gradient; this gives it a
   slow drift so the top of the page is not dead still. 18s and a few percent
   of scale: if it reads as "moving", it is too strong.
   translateX(-50%) is repeated from the base rule because an animation that
   sets transform replaces it outright - dropping it would snap the glow
   sideways by half its own width. */
@keyframes hero-glow-drift {
  0%,
  100% {
    transform: translateX(-50%) scale(1);
    opacity: 1;
  }
  50% {
    transform: translateX(-50%) scale(1.08);
    opacity: 0.82;
  }
}

.hero-glow {
  animation: hero-glow-drift 18s ease-in-out infinite;
}

/* Cards lift toward the reader. Pointer-only: on a touch screen :hover
   sticks after a tap, leaving a card raised until you tap something else. */
@media (hover: hover) and (pointer: fine) {
  .feature-card,
  .screenshots figure {
    transition:
      opacity 0.5s ease,
      transform 0.35s cubic-bezier(0.2, 0.7, 0.2, 1),
      box-shadow 0.35s ease;
  }

  /* Guarded on .in-view so a card still waiting to be revealed cannot be
     yanked up by a stray hover before it has faded in. */
  .feature-card.in-view:hover,
  .screenshots figure:hover {
    transform: translateY(-6px);
    box-shadow: 0 18px 38px rgba(179, 100, 30, 0.16);
  }
}

/* ---------- Live list demo ---------- */
/* The one piece of motion here that is not decoration: it shows the product
   doing the thing the product does, in CSS, with nothing to download and
   nothing to buffer. Items check themselves off on a loop. */
.live-demo {
  background: var(--bg-card);
  border-radius: 18px;
  padding: 20px 22px;
  max-width: 340px;
  margin: 0 auto;
  box-shadow: 0 16px 36px rgba(179, 100, 30, 0.14);
  text-align: left;
}

.live-demo-title {
  margin: 0 0 14px;
  font-weight: 800;
  font-size: 0.95rem;
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.live-demo-count {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--text-secondary);
}

.live-demo-row {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 0;
  border-top: 1px solid rgba(179, 100, 30, 0.12);
}

.live-demo-row:first-of-type {
  border-top: none;
}

.live-demo-box {
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  border: 2px solid var(--text-secondary);
  border-radius: 6px;
  position: relative;
  animation: demo-box 9s linear infinite;
}

.live-demo-box::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 1px;
  width: 5px;
  height: 10px;
  border: solid var(--brand-text);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) scale(0);
  animation: demo-tick 9s linear infinite;
}

.live-demo-text {
  position: relative;
  font-size: 0.93rem;
  color: var(--ink);
}

/* The strike-through grows left to right rather than toggling
   text-decoration, so the line draws itself instead of appearing. */
.live-demo-text::after {
  content: "";
  position: absolute;
  left: 0;
  top: 52%;
  height: 1.5px;
  width: 100%;
  background: var(--text-secondary);
  transform-origin: left center;
  transform: scaleX(0);
  animation: demo-strike 9s linear infinite;
}

@keyframes demo-box {
  0%,
  18% {
    background: transparent;
    border-color: var(--text-secondary);
  }
  24%,
  92% {
    background: var(--success);
    border-color: var(--success);
  }
  100% {
    background: transparent;
    border-color: var(--text-secondary);
  }
}

@keyframes demo-tick {
  0%,
  18% {
    transform: rotate(45deg) scale(0);
  }
  26%,
  92% {
    transform: rotate(45deg) scale(1);
  }
  100% {
    transform: rotate(45deg) scale(0);
  }
}

@keyframes demo-strike {
  0%,
  20% {
    transform: scaleX(0);
  }
  30%,
  92% {
    transform: scaleX(1);
  }
  100% {
    transform: scaleX(0);
  }
}

/* Each row ticks a beat after the one above, so it reads as someone working
   down a list rather than a switch being thrown. */
.live-demo-row:nth-of-type(1) .live-demo-box,
.live-demo-row:nth-of-type(1) .live-demo-box::after,
.live-demo-row:nth-of-type(1) .live-demo-text::after {
  animation-delay: 0s;
}

.live-demo-row:nth-of-type(2) .live-demo-box,
.live-demo-row:nth-of-type(2) .live-demo-box::after,
.live-demo-row:nth-of-type(2) .live-demo-text::after {
  animation-delay: 1.1s;
}

.live-demo-row:nth-of-type(3) .live-demo-box,
.live-demo-row:nth-of-type(3) .live-demo-box::after,
.live-demo-row:nth-of-type(3) .live-demo-text::after {
  animation-delay: 2.2s;
}

.live-demo-row:nth-of-type(4) .live-demo-box,
.live-demo-row:nth-of-type(4) .live-demo-box::after,
.live-demo-row:nth-of-type(4) .live-demo-text::after {
  animation-delay: 3.3s;
}

.live-demo-foot {
  margin: 14px 0 0;
  text-align: center;
  font-size: 0.78rem;
  color: var(--text-secondary);
}

/* ---------- Promo video ---------- */
.video-section {
  padding: 8px 0 56px;
}

.video-frame {
  position: relative;
  max-width: 760px;
  margin: 0 auto;
  border-radius: 18px;
  overflow: hidden;
  background: var(--bg-card);
  box-shadow: 0 22px 48px rgba(179, 100, 30, 0.18);
  /* Reserved from the source's own ratio so the page does not jump when the
     video finishes loading. Avoiding that layout shift is the whole reason
     this is here rather than letting the element size itself. */
  aspect-ratio: 16 / 9;
}

.video-frame video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video-caption {
  margin: 14px 0 0;
  text-align: center;
  font-size: 0.88rem;
  color: var(--text-secondary);
}

/* ---------- Reduced motion ---------- */
/* The site had NO reduced-motion handling before this file, which mattered
   more than it looks: the existing .feature-card reveal starts at opacity 0,
   so a reader who asks for less movement was relying on JavaScript running
   to see those cards at all. Forcing them visible here fixes that as well as
   stopping everything added above.
   `pulse` is index.html's own badge animation, named here because this is
   now the one place the site answers that preference. */
@media (prefers-reduced-motion: reduce) {
  .fade-up,
  .feature-card {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .hero-glow,
  .badge-dot,
  .live-demo-box,
  .live-demo-box::after,
  .live-demo-text::after {
    animation: none !important;
  }

  /* Without the loop, the demo should still read as a finished list rather
     than an empty one. */
  .live-demo-box {
    background: var(--success);
    border-color: var(--success);
  }

  .live-demo-box::after {
    transform: rotate(45deg) scale(1);
  }

  .live-demo-text::after {
    transform: scaleX(1);
  }

  .feature-card.in-view:hover,
  .screenshots figure:hover {
    transform: none;
    box-shadow: none;
  }
}
