/* ===========================================================================
   PIPO - motion layer
   ---------------------------------------------------------------------------
   Kept in its OWN file, not appended to style.css, because it was appended
   there once and a later rsync of the staging folder silently wiped it - the
   markup kept referencing classes that no longer existed, so the cards went
   blank. A separate file survives a redeploy of the base stylesheet.

   Everything here is pure CSS. The site's Content-Security-Policy is
   default-src 'none' with no script-src at all, and that is worth keeping: a
   marketing page is exactly where a stray third-party script ends up. Scroll
   reveals use animation-timeline: view(), so the browser does the work an
   IntersectionObserver normally would.

   Browsers without scroll-driven animations (Safari, older Firefox) see the
   finished state - the @supports guard means nothing ever starts hidden.
   ======================================================================== */

/* --------------------------------------------------- ambient motion --- */
@keyframes pipo-float {
  0%, 100% { transform: translateY(0)     rotate(-1deg); }
  50%      { transform: translateY(-14px) rotate(1deg); }
}
@keyframes pipo-glow {
  0%, 100% { opacity: .45; transform: scale(1); }
  50%      { opacity: .75; transform: scale(1.08); }
}
@keyframes pipo-hop {
  0%, 100% { transform: translateY(0); }
  30%      { transform: translateY(-9px); }
  60%      { transform: translateY(0); }
}

.hero-art img.hero-robot {
  width: min(430px, 78vw);
  height: auto;
  display: block;
  animation: pipo-float 6s ease-in-out infinite;
  filter: drop-shadow(0 26px 34px rgba(16, 42, 80, .28));
}
.hero-art-glow { animation: pipo-glow 6s ease-in-out infinite; }

/* -------------------------------------------------- scroll reveals --- */
@keyframes pipo-rise      { from { opacity:0; transform:translateY(34px); } to { opacity:1; transform:none; } }
@keyframes pipo-rise-left { from { opacity:0; transform:translateX(-32px); } to { opacity:1; transform:none; } }

@supports (animation-timeline: view()) {
  .reveal      { animation: pipo-rise linear both; animation-timeline: view(); animation-range: entry 5% cover 26%; }
  .reveal-left { animation: pipo-rise-left linear both; animation-timeline: view(); animation-range: entry 5% cover 30%; }
  .reveal-stagger > * { animation: pipo-rise linear both; animation-timeline: view(); }
  .reveal-stagger > *:nth-child(1) { animation-range: entry 2%  cover 22%; }
  .reveal-stagger > *:nth-child(2) { animation-range: entry 6%  cover 26%; }
  .reveal-stagger > *:nth-child(3) { animation-range: entry 10% cover 30%; }
  .reveal-stagger > *:nth-child(4) { animation-range: entry 14% cover 34%; }
  .reveal-stagger > *:nth-child(5) { animation-range: entry 18% cover 38%; }
  .reveal-stagger > *:nth-child(6) { animation-range: entry 22% cover 42%; }
}

/* ------------------------------------------------------ pose cards --- */
.pose-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1.1rem;
  margin-top: 1.6rem;
}
.pose-card {
  background: #fff;
  border: 1px solid rgba(120, 150, 190, .22);
  border-radius: 18px;
  padding: 1.1rem .9rem 1rem;
  text-align: center;
  transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.pose-card h3 { font-size: .98rem; margin: .2rem 0 .3rem; }
.pose-card p  { font-size: .85rem; line-height: 1.55; margin: 0; opacity: .82; }
.pose-card:hover,
.pose-card:focus-within {
  transform: translateY(-6px);
  border-color: rgba(34, 211, 238, .55);
  box-shadow: 0 16px 30px rgba(20, 50, 90, .14);
}

/* ------------------------------------------------- sprite strips ----- */
/* steps(n) MUST match the frame count exactly, or the loop slides half a
   robot into view. Counts are written beside each rule so nobody has to
   rediscover them by opening the PNG. */
@keyframes strip8 { to { background-position: -768px 0; } }
@keyframes strip7 { to { background-position: -672px 0; } }

.pipo-strip {
  display: block;
  width: 96px;
  height: 96px;
  margin: 0 auto .5rem;
  background-repeat: no-repeat;
  background-position: 0 0;
  background-size: auto 96px;
}
.strip-wave   { background-image:url('/assets/img/strip_wave.png');   animation:strip8 1.5s steps(8) infinite; }
.strip-talk   { background-image:url('/assets/img/strip_talk.png');   animation:strip8 1.2s steps(8) infinite; }
.strip-love   { background-image:url('/assets/img/strip_love.png');   animation:strip8 1.7s steps(8) infinite; }
.strip-sleep  { background-image:url('/assets/img/strip_sleep.png');  animation:strip8 3.2s steps(8) infinite; }
.strip-bright { background-image:url('/assets/img/strip_bright.png'); animation:strip8 1.4s steps(8) infinite; }
.strip-walk   { background-image:url('/assets/img/strip_walk.png');   animation:strip8 0.9s steps(8) infinite; }
.strip-run    { background-image:url('/assets/img/strip_run.png');    animation:strip7 0.6s steps(7) infinite; }
.strip-dizzy  { background-image:url('/assets/img/strip_dizzy.png');  animation:strip8 1.1s steps(8) infinite; }

/* Hovering a card wakes that PIPO up. The sleeper is the joke - it stays
   asleep however much you hover, which says more than a caption would. */
.pose-card:hover .pipo-strip,
.pose-card:focus-within .pipo-strip { animation-duration: .55s; }
.pose-card:hover .strip-sleep,
.pose-card:focus-within .strip-sleep { animation-duration: 3.2s; }

/* ------------------------------------------------ personality cards --- */
@keyframes pipo-idle-play { to { background-position: -768px 0; } }

.persona-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: 1rem;
  margin-top: 1.5rem;
}
.pipo-idle {
  display: block;
  width: 96px;
  height: 96px;
  margin: 0 auto .35rem;
  background-repeat: no-repeat;
  background-size: 768px 96px;
  background-position: 0 0;
  animation: pipo-idle-play 1.6s steps(8) infinite;
}
/* Slightly different tempos so six robots do not breathe in lockstep. */
.pipo-idle-sunny   { background-image:url('/assets/img/idle_sunny.png');   animation-duration:1.55s; }
.pipo-idle-gentle  { background-image:url('/assets/img/idle_gentle.png');  animation-duration:2.10s; }
.pipo-idle-tricky  { background-image:url('/assets/img/idle_tricky.png');  animation-duration:1.35s; }
.pipo-idle-bashful { background-image:url('/assets/img/idle_bashful.png'); animation-duration:1.95s; }
.pipo-idle-clingy  { background-image:url('/assets/img/idle_clingy.png');  animation-duration:1.70s; }
.pipo-idle-aloof   { background-image:url('/assets/img/idle_aloof.png');   animation-duration:2.40s; }
.persona-card:hover .pipo-idle,
.persona-card:focus-within .pipo-idle { animation-duration: .85s; }

/* --------------------------------------------------------- respect --- */
@media (prefers-reduced-motion: reduce) {
  .hero-art img.hero-robot,
  .hero-art-glow,
  .pipo-strip,
  .pipo-idle,
  .reveal, .reveal-left, .reveal-stagger > * {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    background-position: 0 0 !important;
  }
  .pose-card, .persona-card { transition: none; }
}

/* ----------------------------------------------------------- promo video --- */
/* aspect-ratio rather than a padding-top hack: the element then reserves its
   own height before the poster loads, so the section does not jump. */
.video-frame {
  margin: 1.8rem auto 0;
  max-width: 880px;
  border-radius: 18px;
  overflow: hidden;
  /* No border and no dark fill: the video is 16:9 and so is the box, so
     there is nothing to letterbox - the fill only ever showed as a black
     outline around the player. The shadow alone lifts it off the page. */
  box-shadow: 0 18px 40px rgba(20, 50, 90, .13);
  background: transparent;
  line-height: 0;
}
.promo {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
}
.watch-lede { max-width: 60ch; }
/* ------------------------------------------------------------ buy links --- */
/* Brand colours are on the LEFT EDGE only, not the whole button: six
   full-bleed marketplace colours next to each other fight, and none of them
   is PIPO's. */
.shop-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: .9rem;
  margin-top: 1.5rem;
}
.shop-btn {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  padding: .85rem 1rem .85rem 1.15rem;
  background: #fff;
  border: 1px solid rgba(120, 150, 190, .22);
  border-left: 5px solid var(--shop-accent, #22D3EE);
  border-radius: 14px;
  text-decoration: none;
  color: inherit;
  transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}
.shop-btn:hover,
.shop-btn:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 14px 26px rgba(20, 50, 90, .14);
}
.shop-plat  { font-size: .74rem; letter-spacing: .06em; text-transform: uppercase; opacity: .62; }
.shop-label { font-weight: 650; font-size: 1rem; }

.shop-shopee     { --shop-accent: #EE4D2D; }
.shop-tokopedia  { --shop-accent: #03AC0E; }
.shop-tiktokshop { --shop-accent: #111111; }
.shop-other      { --shop-accent: #5A6779; }