/* ===========================================================================
 *  Loyal Sathi — motion for the public site
 *
 *  A separate file rather than more of site.css, for one reason worth knowing:
 *  everything in here is optional. If it never loads, the site is exactly the
 *  site — nothing depends on it for layout, legibility or reach. That is the
 *  test a decoration should pass before it goes anywhere near a page a shop
 *  owner is deciding on.
 *
 *  THE RULES THIS FILE KEEPS
 *
 *  1. transform and opacity only. They are the two properties a phone can
 *     animate on the compositor without repainting; anything else is how a
 *     marketing page ends up stuttering on the device most of Nepal browses on.
 *  2. Fast. 150–400ms. Motion you notice as motion is motion that is too slow.
 *  3. Attached to something. A hover, a press, an arrival. Nothing loops, and
 *     nothing moves on its own while somebody is trying to read.
 *  4. prefers-reduced-motion turns all of it OFF, not down. That is at the
 *     bottom and it is not optional.
 *
 *  The scroll-reveal itself already lives in site.css and site.js and is not
 *  duplicated here. This adds the parts that were missing: things arriving in
 *  sequence rather than all at once, and surfaces that answer the pointer.
 * ======================================================================== */

/* ------------------------------------------------------------- stagger ----
   The reveal fires a whole grid at once, so six cards appear as one slab. Held
   back a beat each, the eye is led across them instead — the single change that
   most makes a page feel considered rather than assembled.

   Capped at eight: past that the last card waits long enough to look broken,
   and a grid that big is being read as a block anyway. */
.js-reveal .reveal.is-in > *:nth-child(1) { --ls-stagger: 0ms; }
.js-reveal .reveal.is-in > *:nth-child(2) { --ls-stagger: 55ms; }
.js-reveal .reveal.is-in > *:nth-child(3) { --ls-stagger: 110ms; }
.js-reveal .reveal.is-in > *:nth-child(4) { --ls-stagger: 165ms; }
.js-reveal .reveal.is-in > *:nth-child(5) { --ls-stagger: 220ms; }
.js-reveal .reveal.is-in > *:nth-child(6) { --ls-stagger: 275ms; }
.js-reveal .reveal.is-in > *:nth-child(n+7){ --ls-stagger: 310ms; }

@keyframes ls-rise{
  from{ opacity: 0; transform: translate3d(0, 14px, 0); }
  to  { opacity: 1; transform: none; }
}

/*
 * Named containers, not "any grid".
 *
 * On this page the .reveal element IS the list — `ol.flow`, `div.fx-grid`,
 * `ul.feat-list`, `ul.honest` — so the stagger applies to its direct children.
 *
 * `.band-grid` is deliberately absent. It holds exactly two things: a block of
 * copy and the illustration that belongs to it. Staggering those animates a
 * picture away from its own caption, which is the sort of motion that looks
 * expensive in a demo and reads as broken on a real page.
 */
.js-reveal .flow.reveal.is-in > *,
.js-reveal .fx-grid.reveal.is-in > *,
.js-reveal .feat-list.reveal.is-in > *,
.js-reveal .honest.reveal.is-in > *{
  animation: ls-rise 420ms var(--ease, cubic-bezier(.16,1,.3,1)) both;
  animation-delay: var(--ls-stagger, 0ms);
}

/* --------------------------------------------------------- surfaces -------
   A card that lifts slightly under the pointer reads as a thing rather than a
   picture of a thing. Kept to 3px and a shadow: any more is a novelty, and a
   novelty is what a shop owner is trying to work out whether you are. */
.card, .plan, .fx, .step{
  transition:
    transform 220ms var(--ease-out, cubic-bezier(.33,1,.68,1)),
    box-shadow 220ms var(--ease-out, cubic-bezier(.33,1,.68,1));
}
@media (hover: hover) and (pointer: fine){
  .card:hover, .fx:hover, .step:hover{
    transform: translateY(-3px);
    box-shadow: 0 12px 28px rgba(22, 50, 63, .10);
  }
  /* The plans carry a decision, so they lift a touch more when considered. */
  .plan:hover{
    transform: translateY(-4px);
    box-shadow: 0 16px 36px rgba(22, 50, 63, .13);
  }
}

/* ----------------------------------------------------------- controls -----
   Press feedback. A button that does not move when pressed feels, for the
   fraction of a second before the page responds, like a button that is broken. */
.btn{ transition: transform 140ms var(--ease-out, cubic-bezier(.33,1,.68,1)), box-shadow 140ms ease; }
.btn:active{ transform: scale(.985); }

@media (hover: hover) and (pointer: fine){
  .btn-gold:hover{ box-shadow: 0 8px 22px rgba(217, 169, 58, .30); }
}

/* The nav's current-page dot and the links: a quiet underline that grows from
   the left rather than appearing whole. */
@media (hover: hover) and (pointer: fine){
  .site-nav a{ position: relative; }
  .site-nav a::after{
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: -3px;
    height: 2px;
    background: currentColor;
    opacity: .5;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 200ms var(--ease-out, cubic-bezier(.33,1,.68,1));
  }
  .site-nav a:hover::after{ transform: scaleX(1); }
  /* The current page already says so; it does not need to animate as well. */
  .site-nav a[aria-current]::after{ transform: scaleX(1); opacity: .35; }
}

/* --------------------------------------------------------- the hero card --
   The live stamp card in the hero is the one thing on the page that IS the
   product. When a stamp lands it should feel like it landed. */
@keyframes ls-stamp-land{
  0%  { transform: scale(.6); opacity: 0; }
  60% { transform: scale(1.08); opacity: 1; }
  100%{ transform: scale(1); opacity: 1; }
}
.demo-dot.on{ animation: ls-stamp-land 320ms var(--ease-back, cubic-bezier(.34,1.56,.64,1)) both; }

/* ------------------------------------------------------ reduced motion ----
   Off, not slower. Somebody who has told their device to stop animating things
   has usually done it because motion makes them ill, and "subtle" is not an
   exemption. The stagger has to be neutralised explicitly, because an
   animation-delay left behind would hold content invisible. */
@media (prefers-reduced-motion: reduce){
  /* These MUST be the same four containers the stagger targets above. They were
     briefly not, after the selectors were corrected to the real markup and this
     block was left behind — which would have meant reduced-motion silently
     stopped switching the stagger off, and an animation-delay with nothing to
     clear it holds content invisible. Change one list, change both. */
  .js-reveal .flow.reveal.is-in > *,
  .js-reveal .fx-grid.reveal.is-in > *,
  .js-reveal .feat-list.reveal.is-in > *,
  .js-reveal .honest.reveal.is-in > *,
  .demo-dot.on{
    animation: none !important;
    animation-delay: 0ms !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .card, .plan, .fx, .step, .btn, .site-nav a::after{ transition: none !important; }
  .card:hover, .plan:hover, .fx:hover, .step:hover,
  .btn:active{ transform: none !important; box-shadow: none; }
  .site-nav a:hover::after{ transform: scaleX(0); }
}
