/* 黑咪之爪 · motion.
   Pictures loop like photographs in a wizard's newspaper: small, slow, and
   always running while their spread is on screen. Text doesn't move; it inks in
   once, top to bottom, when you turn to the spread. Reduced motion turns it all off. */

.js .sheet:not(.on) *, .js .sheet:not(.on) *::before, .js .sheet:not(.on) *::after { animation-play-state: paused !important; }

/* ---------- Turning to a spread: text inks in ---------- */

.js .sheet .prose p, .js .sheet .lead, .js .sheet .note, .js .sheet .pull p, .js .sheet .pull cite,
.js .sheet .footnote, .js .sheet .fear-text p, .js .sheet .finale-text p, .js .sheet .coda, .js .sheet .box.oikos p {
  -webkit-mask-image: linear-gradient(180deg, #000 45%, transparent 55%);
          mask-image: linear-gradient(180deg, #000 45%, transparent 55%);
  -webkit-mask-size: 100% 240%;
          mask-size: 100% 240%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: 0 100%;
          mask-position: 0 100%;
}
.js .sheet.seen .prose p, .js .sheet.seen .lead, .js .sheet.seen .note, .js .sheet.seen .pull p, .js .sheet.seen .pull cite,
.js .sheet.seen .footnote, .js .sheet.seen .fear-text p, .js .sheet.seen .finale-text p, .js .sheet.seen .coda, .js .sheet.seen .box.oikos p {
  animation: ink-in 1500ms var(--ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 260ms + 150ms);
  animation-play-state: running !important;
}
@keyframes ink-in { to { -webkit-mask-position: 0 0; mask-position: 0 0; } }

/* ---------- Picture loops ---------- */

.boil img { animation: boil 600ms steps(1) infinite; }
@keyframes boil { 0% { filter: url(#boil1); } 33.3% { filter: url(#boil2); } 66.6% { filter: url(#boil3); } }

.breathe img { transform-origin: 50% 100%; animation: breathe 3.8s var(--ease-in-out) infinite; }
.breathe.late img { animation-delay: -1.7s; }
@keyframes breathe { 0%, 100% { transform: scale(1, 1); } 50% { transform: scale(1.012, 1.03); } }

.sway img { transform-origin: 50% 100%; animation: sway 4.4s var(--ease-in-out) infinite; }
.sway.late img { animation-delay: -2.2s; }
@keyframes sway { 0%, 100% { transform: rotate(-1.1deg); } 50% { transform: rotate(1.1deg); } }

.wobble img { animation: wobble 330ms steps(1) infinite; }
@keyframes wobble { 0% { transform: rotate(-0.9deg); } 50% { transform: rotate(0.9deg) translateY(-1px); } }

.shiver img { animation: shiver 2.8s linear infinite; }
@keyframes shiver { 0%, 46%, 100% { transform: none; } 48%, 52%, 56%, 60%, 64% { transform: translateX(-1.5px); } 50%, 54%, 58%, 62% { transform: translateX(1.5px); } }

.pounce-art { transform-origin: 50% 100%; animation: pounce 3.2s var(--ease-out) infinite; }
@keyframes pounce {
  0%, 60%, 100% { transform: none; }
  66% { transform: scale(1.04, 0.94); }
  74% { transform: translate(3%, -7%) scale(0.97, 1.05) rotate(-2deg); }
  84% { transform: translate(5%, 0) scale(1.03, 0.97); }
  92% { transform: translate(5%, 0); }
}

.hopping img { transform-origin: 50% 100%; animation: hop 2.4s var(--ease-out) infinite; }
@keyframes hop { 0%, 70%, 100% { transform: none; } 76% { transform: scale(1.03, 0.96); } 84% { transform: translateY(-4%) scale(0.98, 1.03); } 92% { transform: none; } }

.kick img { animation: kick 3s linear infinite; }
@keyframes kick { 0%, 50%, 100% { transform: none; } 54%, 62%, 70% { transform: rotate(-2.4deg) translateX(-1%); } 58%, 66%, 74% { transform: rotate(2deg) translateX(1%); } 78% { transform: none; } }

/* The vacuum rolls by; Yumi barely lifts a paw. */
@keyframes lazy { 0%, 100% { transform: none; } 40% { transform: translateX(-1.2%) rotate(-0.6deg); } 55% { transform: translateX(0.6%); } }

.notes i { animation: note 3.6s var(--ease-out) infinite; }
.notes i:nth-child(2) { left: 72%; animation-delay: 1.2s; }
.notes i:nth-child(3) { left: 54%; animation-delay: 2.4s; }
@keyframes note { 0% { opacity: 0; transform: translate(0, 10px) rotate(-10deg); } 20% { opacity: 1; } 100% { opacity: 0; transform: translate(18px, -60px) rotate(12deg); } }

.ears::before { content: '♥'; position: absolute; left: 30%; top: 0; font: 20px/1 var(--serif); color: var(--ink-red); opacity: 0; animation: heart 4.2s var(--ease-spring) infinite 1s; }
@keyframes heart { 0%, 60%, 100% { opacity: 0; transform: scale(0.4); } 68% { opacity: 1; transform: scale(1.15) translateY(-6px); } 80% { opacity: 1; transform: scale(1) translateY(-10px); } 92% { opacity: 0; transform: translateY(-18px); } }

/* Yumi slides out of the door gap, looks, and slips back. */
.peek-gap .peek { animation: peek 7s var(--ease-in-out) infinite 1.2s; }
@keyframes peek {
  0%, 10%, 76%, 100% { transform: translateX(-100%); }
  24%, 36% { transform: translateX(-38%); }
  44% { transform: translateX(-38%) rotate(-4deg); }
  54%, 64% { transform: translateX(-12%) rotate(2deg); }
}

.pot-loop .steam { animation: steam 3.4s var(--ease-out) infinite; }
.pot-loop .steam.two { animation-delay: 1.7s; }
@keyframes steam { 0% { opacity: 0; transform: translateY(18%) scale(0.9, 0.8); } 30% { opacity: 0.85; } 100% { opacity: 0; transform: translateY(-28%) scale(1.05, 1.2) skewX(-6deg); } }

.chain li::after { animation: carry 4s var(--ease-in-out) infinite; }
.chain li:nth-child(3)::after { animation-delay: 1s; }
.chain li:nth-child(4)::after { animation-delay: 2s; }
@keyframes carry { 0% { opacity: 0; transform: translateY(0); } 4% { opacity: 1; } 22% { opacity: 1; transform: translateY(calc(var(--u) * 1.4)); } 26%, 100% { opacity: 0; transform: translateY(calc(var(--u) * 1.4)); } }

.carer .arr.back { animation: dash 1.6s linear infinite; }
@keyframes dash { to { stroke-dashoffset: -18; } }

.results li { animation: loading 1.6s var(--ease-in-out) infinite; }
.results li:nth-child(2) { animation-delay: 0.2s; }
.results li:nth-child(3) { animation-delay: 0.4s; }
@keyframes loading { 50% { opacity: 0.45; transform: scaleX(0.92); } }
.caret { animation: caret 1s steps(1) infinite; }
@keyframes caret { 50% { opacity: 0; } }

/* Cover: the cat walks the staff, 8-frame walk cycle; the notes breathe. */
.walk-cat { animation: gait 720ms steps(8, jump-none) infinite paused; }
.sheet.on .walk-cat, .walker.walking { animation-play-state: running; }
@keyframes gait { from { background-position: 0 0; } to { background-position: 100% 0; } }
.singer { animation: stroll 18s linear infinite; }
.back-cover .singer { animation-delay: -9s; }
@keyframes stroll { from { transform: translateX(-2cqw); } to { transform: translateX(40cqw); } }
.singer b { animation: sing 2.4s var(--ease-out) infinite; }
.singer b:nth-of-type(2) { animation-delay: 0.8s; }
.singer b:nth-of-type(3) { animation-delay: 1.6s; }
@keyframes sing { 0% { opacity: 0; transform: translate(0, 0) scale(0.6); } 20% { opacity: 1; } 100% { opacity: 0; transform: translate(140%, -180%) rotate(18deg) scale(1.1); } }
.sheet-note { transform-origin: 50% 80%; animation: breathe 4.8s ease-in-out infinite; }
.n2 { animation-delay: -1.2s; } .n3 { animation-delay: -2.4s; } .n4 { animation-delay: -3.6s; }
@keyframes breathe { 0%, 100% { transform: translateY(-55%) scale(0.9) rotate(-7deg); opacity: 0.5; } 50% { transform: translateY(-95%) scale(1.16) rotate(6deg); opacity: 1; } }

/* ---------- Flip cards: a little wiggle now and then; the corner mark nods ---------- */

.flip.idle[aria-pressed='false'] { animation: nudge 4.6s var(--ease-in-out) infinite 1s; }
.flip.play.idle[aria-pressed='false'] { animation-delay: 3.3s; }
@keyframes nudge { 0%, 70%, 100% { transform: none; } 74% { transform: rotate(-2.4deg) translateY(-2px); } 78% { transform: rotate(2.2deg); } 82% { transform: rotate(-1.4deg); } 86% { transform: rotate(0.8deg); } 90% { transform: none; } }
.flip.idle .flip-hint { animation: hint 4.6s var(--ease-in-out) infinite 1s; transform-origin: 50% 50%; }
@keyframes hint { 0%, 68%, 100% { transform: none; } 76% { transform: rotateY(180deg) scale(1.15); } 86% { transform: rotateY(360deg); } }
.flip[aria-pressed='true'] .claw path { animation: draw 260ms var(--ease-out) forwards 420ms; }
.flip[aria-pressed='true'] .claw path:nth-child(2) { animation-delay: 500ms; }
.flip[aria-pressed='true'] .claw path:nth-child(3) { animation-delay: 580ms; }
.flip[aria-pressed='true'] .big-glyph { animation: flinch 500ms linear 600ms; }
@keyframes flinch { 20%, 60% { transform: translateX(-4px) rotate(-3deg); } 40%, 80% { transform: translateX(4px) rotate(3deg); } }
@keyframes draw { to { stroke-dashoffset: 0; } }
.small-text.after { opacity: 0; transform: translateY(6px); transition: opacity 500ms, transform 500ms var(--ease-out); }
.flip[aria-pressed='true'] .small-text.after { opacity: 1; transform: none; transition-delay: 2.2s; }
.flip:hover .face.front { box-shadow: 9px 9px 0 var(--ink-yellow); }
.flip:hover .face.back { box-shadow: 9px 9px 0 var(--ink-red); }

/* ---------- The orbit sways back and forth while its spread is on screen ---------- */

.orbit { animation: sway 16s var(--ease-in-out) infinite alternate paused; }
.sheet.on .orbit { animation-play-state: running; }
@keyframes sway { from { --spin: -16deg; } to { --spin: 16deg; } }

/* ---------- One-shot moments when a spread arrives ---------- */

.js .stamp { opacity: 0; }
.js .sheet.seen .stamp { animation: stamp 520ms var(--ease-out) forwards 900ms; animation-play-state: running !important; }
.js .sheet.seen .page.r .stamp { animation-delay: 1700ms; }
@keyframes stamp { 0% { opacity: 0; transform: rotate(var(--rot, -14deg)) scale(1.8); } 60% { opacity: 1; transform: rotate(var(--rot, -14deg)) scale(0.94); } 100% { opacity: 1; transform: rotate(var(--rot, -14deg)) scale(1); } }
.listing.chosen .stamp { --rot: 9deg; }

.js .stats dd::before { transform: scaleX(0); }
.js .sheet.seen .stats dd::before { transform: scaleX(1); transition: transform 900ms var(--ease-out) 600ms; }
.js .sheet.seen .stats div:nth-child(7) dd::before { transition-delay: 1400ms; transition-timing-function: var(--ease-spring); }

/* Speech bubbles, driven by motion.js (adds .pop / .gone). */
.bubble { transform-origin: 12px 100%; opacity: 0; transform: scale(0.6) rotate(-4deg); }
.bubble.pop { opacity: 1; transform: none; transition: transform 420ms var(--ease-spring), opacity 160ms linear; }
.bubble.gone { opacity: 0; transform: scale(0.85) translateY(-4px); transition: transform 240ms var(--ease-out), opacity 240ms linear; }
.bubble .typed { visibility: hidden; }
.bubble .typed.in { visibility: visible; }

.js .chapter-head .cell b { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .js .sheet .prose p, .js .sheet .lead, .js .sheet .note, .js .sheet .pull p, .js .sheet .pull cite,
  .js .sheet .footnote, .js .sheet .fear-text p, .js .sheet .finale-text p, .js .sheet .coda, .js .sheet .box.oikos p { -webkit-mask-image: none; mask-image: none; }
  .js .chapter-head .cell b, .js .stamp, .bubble, .small-text.after { opacity: 1 !important; transform: none; }
  .js .stats dd::before { transform: none; }
  .claw path, .cell .scratch path { stroke-dashoffset: 0; }
  .runner, .cell .leaf { display: none; }
  .singer { transform: translateX(30cqw); }
  .peek-gap .peek { transform: translateX(-30%); }
}

@media print {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .js .sheet .prose p, .js .sheet .lead, .js .sheet .note, .js .sheet .pull p, .js .sheet .pull cite,
  .js .sheet .footnote, .js .sheet .fear-text p, .js .sheet .finale-text p, .js .sheet .coda, .js .sheet .box.oikos p { -webkit-mask-image: none; mask-image: none; }
  .js .chapter-head .cell b, .js .stamp, .bubble, .small-text.after { opacity: 1 !important; transform: none; }
  .js .stamp { transform: rotate(var(--rot, -14deg)) !important; }
  .js .stats dd::before { transform: none; }
  .bubble .typed { visibility: visible; }
  .runner, .cell .leaf, .cell .pawprint, .cell .scratch { display: none; }
  .singer { transform: translateX(30cqw); }
  .peek-gap .peek { transform: translateX(-30%); }
  .claw path { stroke-dashoffset: 0; }
}
