/* ============================================================================
   Motion — shared by the Lucky Cat landing and the Nock page
   ----------------------------------------------------------------------------
   Everything here is gated on `html.motion`, which motion.js only adds when
   JavaScript runs AND the system is not asking for reduced motion. Without that
   class the page is fully visible and static: no content is ever hidden behind
   an animation that might not fire.

   Only opacity and transform are animated. Easing is exponential ease-out —
   fast départ, long settle, no overshoot.
   ========================================================================= */

:root {
  --e-out:  cubic-bezier(.16, 1, .3, 1);    /* the long settle */
  --e-soft: cubic-bezier(.22, 1, .36, 1);   /* short UI moves */
  --d-rev:  .72s;
}

/* --- generic reveal -------------------------------------------------------- */
html.motion [data-reveal] { opacity: 0; transform: translateY(16px); }
html.motion [data-reveal].is-in {
  opacity: 1; transform: none;
  transition: opacity var(--d-rev) var(--e-out), transform var(--d-rev) var(--e-out);
}

/* --- staggered children ---------------------------------------------------- */
/* One entrance per item, 70ms apart, so a row reads left to right instead of
   arriving as a single block. */
html.motion [data-reveal="stagger"] { opacity: 1; transform: none; }
html.motion [data-reveal="stagger"] > * { opacity: 0; transform: translateY(14px); }
html.motion [data-reveal="stagger"].is-in > * {
  opacity: 1; transform: none;
  transition: opacity .62s var(--e-out), transform .62s var(--e-out);
}
html.motion [data-reveal="stagger"].is-in > :nth-child(1) { transition-delay: 0ms; }
html.motion [data-reveal="stagger"].is-in > :nth-child(2) { transition-delay: 70ms; }
html.motion [data-reveal="stagger"].is-in > :nth-child(3) { transition-delay: 140ms; }
html.motion [data-reveal="stagger"].is-in > :nth-child(4) { transition-delay: 210ms; }
html.motion [data-reveal="stagger"].is-in > :nth-child(5) { transition-delay: 280ms; }
html.motion [data-reveal="stagger"].is-in > :nth-child(6) { transition-delay: 350ms; }

/* --- the handoff: a missed call becoming a job card ------------------------ */
/* The page's whole argument in one move. The dead card is already there, the
   arrow travels, and the job card lands after it — in that order, because that
   is the claim being made. */
html.motion [data-motion="handoff"] .dead-card { opacity: 0; transform: translateY(14px); }
html.motion [data-motion="handoff"] .tarrow    { opacity: 0; transform: translateX(-14px); }
html.motion [data-motion="handoff"] .job       { opacity: 0; transform: translateY(22px) scale(.985); }
html.motion [data-motion="handoff"].is-in .dead-card,
html.motion [data-motion="handoff"].is-in .tarrow,
html.motion [data-motion="handoff"].is-in .job {
  opacity: 1; transform: none;
  transition: opacity .7s var(--e-out), transform .7s var(--e-out);
}
html.motion [data-motion="handoff"].is-in .tarrow { transition-delay: .34s; }
html.motion [data-motion="handoff"].is-in .job    { transition-delay: .46s; }

/* --- the thread: messages arriving like messages --------------------------- */
/* Nock's replies come from its side, the customer's from theirs, at a cadence
   close to someone actually typing. */
html.motion [data-motion="thread"] .bub { opacity: 0; transform: translateY(10px); }
html.motion [data-motion="thread"] .bub-nock { transform: translate(-10px, 10px); }
html.motion [data-motion="thread"] .bub-cust { transform: translate(10px, 10px); }
html.motion [data-motion="thread"].is-in .bub {
  opacity: 1; transform: none;
  transition: opacity .5s var(--e-out), transform .5s var(--e-out);
}
html.motion [data-motion="thread"].is-in .bub:nth-child(1) { transition-delay: 0ms; }
html.motion [data-motion="thread"].is-in .bub:nth-child(2) { transition-delay: 260ms; }
html.motion [data-motion="thread"].is-in .bub:nth-child(3) { transition-delay: 620ms; }
html.motion [data-motion="thread"].is-in .bub:nth-child(4) { transition-delay: 900ms; }
html.motion [data-motion="thread"].is-in .bub:nth-child(5) { transition-delay: 1200ms; }

/* --- the fork: one first line, two different sets of questions ------------- */
/* The branches separate as they arrive, which is the point being made. */
html.motion [data-motion="fork"] > .branch { opacity: 0; }
html.motion [data-motion="fork"] > .branch:nth-child(1) { transform: translateX(-16px); }
html.motion [data-motion="fork"] > .branch:nth-child(2) { transform: translateX(16px); }
html.motion [data-motion="fork"].is-in > .branch {
  opacity: 1; transform: none;
  transition: opacity .68s var(--e-out), transform .68s var(--e-out);
}
html.motion [data-motion="fork"].is-in > .branch:nth-child(2) { transition-delay: 90ms; }

/* --- the lineup: four products, then the empty slot ------------------------ */
/* The open chip waits, so "and yours" lands as its own beat. */
html.motion [data-motion="lineup"] .chip { opacity: 0; transform: translateY(12px); }
html.motion [data-motion="lineup"].is-in .chip {
  opacity: 1; transform: none;
  transition: opacity .55s var(--e-out), transform .55s var(--e-out);
}
html.motion [data-motion="lineup"].is-in .chip:nth-child(1) { transition-delay: 0ms; }
html.motion [data-motion="lineup"].is-in .chip:nth-child(2) { transition-delay: 80ms; }
html.motion [data-motion="lineup"].is-in .chip:nth-child(3) { transition-delay: 160ms; }
html.motion [data-motion="lineup"].is-in .chip:nth-child(4) { transition-delay: 240ms; }
html.motion [data-motion="lineup"].is-in .chip-open         { transition-delay: 460ms; }

/* --- the steps: a rule drawn under each number ----------------------------- */
/* The rule grows left to right in sequence, which is the same information the
   numbers carry. The border is handed to a pseudo-element so it can scale. */
html.motion [data-motion="steps"] li { border-top-color: transparent; position: relative; }
html.motion [data-motion="steps"] li::before {
  content: ""; position: absolute; top: -2px; left: 0; width: 100%; height: 2px;
  background: var(--border); transform: scaleX(0); transform-origin: left;
}
html.motion [data-motion="steps"] li:first-child::before { background: var(--gold); }
html.motion [data-motion="steps"] li > * { opacity: 0; transform: translateY(12px); }
html.motion [data-motion="steps"].is-in li::before {
  transform: scaleX(1); transition: transform .66s var(--e-out);
}
html.motion [data-motion="steps"].is-in li > * {
  opacity: 1; transform: none;
  transition: opacity .58s var(--e-out), transform .58s var(--e-out);
}
html.motion [data-motion="steps"].is-in li:nth-child(1)::before,
html.motion [data-motion="steps"].is-in li:nth-child(1) > * { transition-delay: 0ms; }
html.motion [data-motion="steps"].is-in li:nth-child(2)::before,
html.motion [data-motion="steps"].is-in li:nth-child(2) > * { transition-delay: 110ms; }
html.motion [data-motion="steps"].is-in li:nth-child(3)::before,
html.motion [data-motion="steps"].is-in li:nth-child(3) > * { transition-delay: 220ms; }
html.motion [data-motion="steps"].is-in li:nth-child(4)::before,
html.motion [data-motion="steps"].is-in li:nth-child(4) > * { transition-delay: 330ms; }

/* --- hero stage drift ------------------------------------------------------ */
/* The devices sit at slightly different depths, so they part company a little
   as the page scrolls. Driven by a custom property motion.js writes, and only
   where there is room for it to read as depth rather than wobble. */
/* The phones carry their tilt on the separate `rotate` property, so transform
   is free for the drift and the angles stay exactly as designed. */
@media (min-width: 900px) {
  html.motion .stage-tablet        { transform: translateY(calc(var(--drift, 0) * -14px)); }
  html.motion .stage-phone.is-left { transform: translateY(calc(var(--drift, 0) * 26px)); }
  html.motion .stage-phone.is-right{ transform: translateY(calc(var(--drift, 0) * 34px)); }
}

/* --- chip hover ------------------------------------------------------------ */
/* Pointing at one product dims the others: the lineup responds as a set. */
html.motion .chip { transition: transform .2s var(--e-soft), opacity .2s var(--e-soft), box-shadow .2s; }
html.motion .lineup:hover .chip:not(:hover) { opacity: .62; }
html.motion .chip:hover { transform: translateY(-2px); }

/* --- print ----------------------------------------------------------------- */
/* Printing never scrolls, so the observer never fires for anything below the
   first screen. Without this, half the page prints blank. */
@media print {
  html.motion [data-reveal],
  html.motion [data-reveal] > *,
  html.motion [data-motion] *,
  html.motion [data-motion] > * {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  html.motion [data-motion="steps"] li { border-top-color: var(--border); }
  html.motion [data-motion="steps"] li:first-child { border-top-color: var(--gold); }
  html.motion [data-motion="steps"] li::before { display: none; }
}

/* --- last resort ----------------------------------------------------------- */
/* Belt and braces: if the class is somehow present while the OS asks for
   reduced motion, everything collapses to its resting state. */
@media (prefers-reduced-motion: reduce) {
  html.motion [data-reveal],
  html.motion [data-reveal] > *,
  html.motion [data-motion] *,
  html.motion [data-motion] > * {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  html.motion [data-motion="steps"] li { border-top-color: var(--border); }
  html.motion [data-motion="steps"] li:first-child { border-top-color: var(--gold); }
  html.motion [data-motion="steps"] li::before { display: none; }
  html.motion .stage-tablet, html.motion .stage-phone { transform: none; }
}
