/* Tiny Baby homepage (index.html). Every picture is a flat felt cut-out. Pieces start laid flat and
   stand up 90 degrees, back to front (the stand keyframes); afterwards each keeps a small idle motion, and js/canvas.js
   ties the hero parallax, the clouds, the Talk sun, and the Sleep moon to scrolling. */
:root { --paper: #f6eee3; }
body { background: var(--paper); }
/* the wordmark and links sit straight on the sky, with nothing behind them */
.site-header .wordmark, .site-nav { background: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
.site-header .wordmark { padding: 0; margin-left: 0; }
.site-nav { padding: 0; }
.site-nav a { color: var(--ink); }

/* ---------- a paper piece: --x is its centre and --b its base line (percent of the scene), --w its width ---------- */
.piece {
  position: absolute; display: block; max-width: none; height: auto; margin: 0;
  pointer-events: none; user-select: none; -webkit-user-select: none;
  left: calc(var(--x) * 1%); top: calc(var(--b) * 1%); width: calc(var(--w) * var(--unit, 1%));
  translate: -50% calc(-100% + var(--shift, 0) * 1px);
  transform-origin: 50% 100%;
}
/* each piece waits flat and unseen on the open canvas, then rises from a sliver of paper (80 degrees; Safari draws
   nothing for a piece at exactly 90) to standing, settling with a small paper spring (html.js is set before first paint) */
.js .stand { rotate: x 80deg; opacity: 0; }
.is-up .stand { animation: stand 1100ms cubic-bezier(0.3, 0.6, 0.35, 1) calc(var(--d, 0) * 1ms) both, var(--idle, none); }
@keyframes stand {
  0% { rotate: x 80deg; opacity: 0; }
  8% { opacity: 1; }
  60% { rotate: x -10deg; }
  80% { rotate: x 3.5deg; }
  100% { rotate: x 0deg; opacity: 1; }
}
/* idle motion, once the piece has stood up. Every loop starts and ends at rest, so nothing snaps when it begins, and
   moves like a pendulum: fastest through the middle, easing at each end (sine curves). */
.sway { --idle: sway 11s linear calc(var(--d, 0) * 1ms + 1100ms) infinite; }
.drift { --idle: drift 48s linear calc(var(--d, 0) * 1ms + 1100ms) infinite; }
.rock { --idle: rock 7.6s linear calc(var(--d, 0) * 1ms + 1100ms) infinite; }
.bob { --idle: bob 3.4s linear calc(var(--d, 0) * 1ms + 1100ms) infinite; }
@keyframes sway {
  0% { transform: rotate(0deg); animation-timing-function: cubic-bezier(0.61, 1, 0.88, 1); }
  25% { transform: rotate(-1.4deg); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  75% { transform: rotate(1.4deg); animation-timing-function: cubic-bezier(0.12, 0, 0.39, 0); }
  100% { transform: rotate(0deg); }
}
@keyframes drift {
  0% { transform: translateX(0); animation-timing-function: cubic-bezier(0.61, 1, 0.88, 1); }
  25% { transform: translateX(-8%); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  75% { transform: translateX(8%); animation-timing-function: cubic-bezier(0.12, 0, 0.39, 0); }
  100% { transform: translateX(0); }
}
@keyframes rock {
  0% { transform: rotate(0deg); animation-timing-function: cubic-bezier(0.61, 1, 0.88, 1); }
  25% { transform: rotate(-1.1deg); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  75% { transform: rotate(1.1deg); animation-timing-function: cubic-bezier(0.12, 0, 0.39, 0); }
  100% { transform: rotate(0deg); }
}
@keyframes bob {
  0% { transform: none; animation-timing-function: cubic-bezier(0.61, 1, 0.88, 1); }
  25% { transform: translateY(-4%) rotate(-1.5deg); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  75% { transform: translateY(0.5%) rotate(0.4deg); animation-timing-function: cubic-bezier(0.12, 0, 0.39, 0); }
  100% { transform: none; }
}

/* ---------- hero: one sunny morning, full bleed ---------- */
.canvas-hero {
  --hs: 0;
  position: relative; height: 100svh; min-height: 620px; max-height: 1100px; overflow: hidden;
  background: var(--grain), linear-gradient(180deg, #f4ece1 0%, #f1e7d8 50%, #cad7ab 68%, #b2c491 100%);
  background-size: 160px 160px, auto;
}
/* the eye sits just below the top edge: low enough that a piece lying flat reads as flat, high enough to still see it */
.canvas-hero .scene { position: absolute; inset: 0; perspective: 1300px; perspective-origin: 50% 5%; }
.canvas-hero .piece { --shift: calc(var(--hs) * var(--depth, 0)); }
.canvas-hero .obj { --unit: min(1vw, 1.6svh); }
/* the sky is one plain paper panel, a little taller than the screen so no canvas shows above it as it lifts; the sun
   and clouds are their own pieces */
.h-sky {
  height: calc((var(--b) + 12) * 1%);
  background: var(--grain), radial-gradient(120% 55% at 50% 100%, rgba(255, 236, 210, 0.95), rgba(255, 236, 210, 0) 70%),
    linear-gradient(180deg, #9cb8ee 0%, #b3c8f2 40%, #d8def1 72%, #f3e4d3 100%);
  background-size: 160px 160px, auto, auto;
}
.flip { scale: -1 1; }

/* --d is when each piece starts to stand (ms): back to front, about a fifth of a second apart */
.h-sky     { --x: 50;  --b: 72;  --w: 104; --d: 120;  --depth: 0.5; }
.h-sun     { --x: 87;  --b: 27;  --w: 8;   --d: 560;  --depth: 0.48; }
.h-cloud1  { --x: 13;  --b: 30;  --w: 12;  --d: 680;  --depth: 0.45; }
.h-cloud2  { --x: 73;  --b: 38;  --w: 9;   --d: 780;  --depth: 0.45; }
.h-far     { --x: 50;  --b: 80;  --w: 122; --d: 700;  --depth: 0.38; }
.h-round   { --x: 9.5; --b: 70;  --w: 11;  --d: 880;  --depth: 0.3; }
.h-mid     { --x: 50;  --b: 96;  --w: 112; --d: 980;  --depth: 0.25; }
.h-cottage { --x: 23;  --b: 80;  --w: 27;  --d: 1150; --depth: 0.2; }
.h-apple   { --x: 82;  --b: 82;  --w: 21;  --d: 1300; --depth: 0.2; }
.h-family  { --x: 56;  --b: 93;  --w: 21;  --d: 1480; --depth: 0.1; }
.h-meadow  { --x: 50;  --b: 104; --w: 104; --d: 1800; --depth: 0; }

/* paper birds cross the sky, flapping between two cut-outs */
.bird { position: absolute; left: 0; top: var(--top); width: calc(var(--size) * min(1vw, 1.6svh)); aspect-ratio: 1.263; opacity: 0; pointer-events: none; }
.bird img { position: absolute; left: 0; top: 50%; width: 100%; height: auto; translate: 0 -50%; }
.bird img:first-child { animation: wings-a 400ms step-end infinite; }
.bird img:last-child { animation: wings-b 400ms step-end infinite; }
.b1 { --top: 19%; --size: 3.8; }
.b2 { --top: 26%; --size: 2.4; }
.is-up .b1 { animation: fly 21s linear 2.9s infinite; }
.is-up .b2 { animation: fly 26s linear 6s infinite; }
@keyframes wings-a { 0% { opacity: 1; } 50% { opacity: 0; } }
@keyframes wings-b { 0% { opacity: 0; } 50% { opacity: 1; } }
@keyframes fly {
  0% { opacity: 0; transform: translate(-12vw, 0); }
  5% { opacity: 1; }
  50% { transform: translate(50vw, -3svh); }
  95% { opacity: 1; }
  100% { opacity: 0; transform: translate(108vw, 1svh); }
}

.canvas-copy {
  position: absolute; z-index: 3; left: 50%; top: clamp(92px, 12.5svh, 132px);
  width: min(54rem, calc(100% - 40px)); text-align: center;
  translate: -50% calc(var(--hs) * 0.35px); opacity: calc(1 - var(--hs) / 520);
}
.canvas-copy h1 { font-size: clamp(2.6rem, 5.2vw, 4.8rem); margin-bottom: 0.28em; }
@media (min-width: 900px) { .canvas-copy h1 .line { display: inline; } .canvas-copy h1 .line--italic::before { content: " "; } }
.canvas-copy .lede { color: #2c3a55; margin: 0 auto 1.4rem; }

/* ---------- app sections: a small paper scene that stands up as you reach it, then keeps moving ---------- */
.app {
  display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: clamp(32px, 6vw, 104px); align-items: center;
  padding: clamp(56px, 5vw, 72px) max(clamp(24px, 6vw, 96px), calc((100% - 1280px) / 2 + 96px));
}
.app--flip .app-art { order: -1; }
.app--talk { background: linear-gradient(180deg, var(--paper), #fdf1df); }
.app--taste { background: linear-gradient(180deg, #fdf1df, #fbf4ec); }
.app--sleep { background: linear-gradient(180deg, #1c2742, #151d33); color: #fff; }
.app--sleep .app-id p, .app--sleep .chapter-body, .app--sleep .time { color: var(--moon-text); }
.time { margin: 0 0 18px; font: italic 400 1.0625rem/1 var(--serif); color: var(--ink-soft); }

.app-art { --p: 0.5; position: relative; margin: 0 4% 6% 0; }
.scene-card {
  --rise: 1;
  position: relative; aspect-ratio: 4 / 3; border-radius: 24px; overflow: hidden; isolation: isolate;
  perspective: 900px; perspective-origin: 50% 5%;
  box-shadow: 0 34px 70px -40px rgba(60, 40, 20, 0.55), 0 0 0 1px rgba(120, 90, 60, 0.08);
}
.phone {
  position: absolute; z-index: 2; width: 25%; right: -4%; bottom: -14%; margin: 0;
  padding: 1.1%; border-radius: 13.5% / 6.5%; background: #fffaf3;
  box-shadow: 0 22px 44px -18px rgba(40, 30, 20, 0.55), 0 0 0 1px rgba(120, 90, 60, 0.12);
  rotate: 4deg; translate: 0 calc((0.5 - var(--p)) * 80px);
}
/* the frame takes the screenshot's exact shape, so the whole screen shows, status bar to tab bar */
.phone img { display: block; width: 100%; height: auto; aspect-ratio: 600 / 1304; object-fit: contain; border-radius: 10% / 4.6%; }
.app--flip .phone { right: -1%; }
.app--sleep .phone { background: #232f52; box-shadow: 0 22px 44px -18px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(201, 207, 224, 0.3); }

/* Tiny Talk: a morning where the sun climbs as you scroll */
.scene-talk { background: var(--grain), linear-gradient(180deg, #b4c8f1 0%, #d9def0 40%, #f4e6d6 58%, #c8d5a9 68%, #b4c592 100%); background-size: 160px 160px, auto; }
.sun { position: absolute; left: 20%; top: 8%; width: 15%; height: auto; max-width: none; translate: -50% calc((1 - var(--rise)) * 230%); }
.t-cloud1 { --x: 46; --b: 30; --w: 18; --d: 80;  left: calc((var(--x) + (var(--p) - 0.5) * 30) * 1%); }
.t-cloud2 { --x: 70; --b: 20; --w: 11; --d: 140; left: calc((var(--x) - (var(--p) - 0.5) * 22) * 1%); }
.t-far    { --x: 50; --b: 78; --w: 160; --d: 0; }
.t-parent { --x: 25; --b: 95; --w: 34; --d: 200; }
.t-baby   { --x: 55; --b: 92; --w: 16; --d: 320; }
.t-meadow { --x: 50; --b: 101; --w: 198; --d: 440; }

/* pieces that hang from the ceiling drop in on their cord, then swing a little */
.hang { position: absolute; height: auto; max-width: none; pointer-events: none; translate: -50% 0; transform-origin: 50% 0; }
.js .hang { translate: -50% -115%; }
.is-up .hang { animation: drop 1000ms cubic-bezier(0.3, 1.25, 0.5, 1) var(--drop, 600ms) both, swing calc(var(--swing, 4.8s) * 2) linear calc(var(--drop, 600ms) + 1000ms) infinite; }
@keyframes drop { from { translate: -50% -115%; } to { translate: -50% 0; } }
@keyframes swing {
  0% { rotate: 0deg; animation-timing-function: cubic-bezier(0.61, 1, 0.88, 1); }
  25% { rotate: calc(var(--amp, 5deg) * -1); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  75% { rotate: var(--amp, 5deg); animation-timing-function: cubic-bezier(0.12, 0, 0.39, 0); }
  100% { rotate: 0deg; }
}
.room-floor { position: absolute; left: 0; right: 0; bottom: 0; }

/* Tiny Taste: lunch at home. A spoon comes in, the baby takes a bite, the lamp sways */
.scene-taste {
  background: var(--grain), repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.28) 0 16px, rgba(255, 255, 255, 0) 16px 32px),
    linear-gradient(180deg, #f6e7d2, #f1dfc6);
  background-size: 160px 160px, auto, auto;
}
.scene-taste .room-floor { height: 26%; box-shadow: 0 -5px 0 #fbf3e6, 0 -7px 0 rgba(150, 110, 70, 0.18);
  background: var(--grain), repeating-linear-gradient(90deg, rgba(120, 80, 40, 0.14) 0 2px, rgba(120, 80, 40, 0) 2px 72px), linear-gradient(180deg, #d9b285, #c99d6d);
  background-size: 160px 160px, auto, auto; }
.k-window    { --x: 22; --b: 46; --w: 28; --d: 0; }
.k-shelf     { --x: 64; --b: 31; --w: 24; --d: 80; }
.k-lamp      { left: 46%; top: -1%; width: 10%; --drop: 400ms; --amp: 2.5deg; --swing: 5.5s; }
.k-sideboard { --x: 13; --b: 86; --w: 24; --d: 160; }
.k-plant     { --x: 71; --b: 96; --w: 12; --d: 220; }
.k-chair     { --x: 40; --b: 97; --w: 26; --d: 280; }
/* placed so the spoon's tip meets the baby's mouth (measured from the art) when the feed loop brings it in */
.k-spoon     { --x: 62.56; --b: 71.9; --w: 44; opacity: 0; }
/* version B's arm, a rig of the same felt (tools/arm_rig.py prints these numbers): the sleeve runs off the card to a
   shoulder it turns about, the hand turns at the wrist under the cuff, the food comes off the spoon at each bite, and
   the front of the baby's bowl is drawn over the spoon so the scoop dips into it */
.k-arm       { --x: 76.401; --b: 71.012; --w: 72.564; aspect-ratio: 1321 / 554; transform-origin: 99.924% 22.037%; opacity: 0; display: none; }
.k-bowl      { display: none; }
[data-motion="b"] .k-arm, [data-motion="b"] .k-bowl { display: block; }
[data-motion="b"] .k-spoon { display: none; }
.arm-hand    { position: absolute; inset: 0; transform-origin: 38.759% 74.819%; }
.arm-part    { position: absolute; display: block; max-width: none; height: auto; }
.arm-hand-art { left: 0; top: 46.029%; width: 60.257%; }
/* the scoop is drawn a little smaller than the art's heaped spoon, closer to a baby-sized bite */
.arm-food    { left: 0.606%; top: 55.235%; width: 7.949%; scale: 0.78 0.66; transform-origin: 50% 95%; }
.arm-sleeve  { left: 36.639%; top: 0.542%; width: 63.361%; }

@keyframes spoon-in { from { opacity: 0; transform: translate(40%, 14%) rotate(6deg); } to { opacity: 1; transform: translate(22%, 10%) rotate(5deg); } }

/* Tiny Sleep: a nursery at night. The baby sleeps on their back with nothing else in the crib; the mobile and the star
   garland turn, the lamp glows, and the moon rises in the window as you scroll */
.scene-sleep { background: var(--grain), radial-gradient(ellipse 80% 70% at 45% 70%, #2d3b69, #1d2747 72%); background-size: 160px 160px, auto; }
.scene-sleep .room-floor { height: 28%; box-shadow: 0 -4px 0 #2a3560;
  background: var(--grain), linear-gradient(180deg, #3a4676, #2e3963); background-size: 160px 160px, auto; }
.s-window { --x: 19; --b: 44; --w: 26; --d: 0; }
.s-window > img { display: block; width: 100%; height: auto; }
/* the window's glass, measured from the art: the moon rises inside it */
.pane { position: absolute; left: 30%; top: 22%; width: 41%; height: 62%; overflow: hidden; border-radius: 50% 50% 4% 4% / 32% 32% 4% 4%; }
.moon { position: absolute; left: 62%; top: 8%; width: 46%; height: auto; max-width: none; translate: -50% calc((1 - var(--rise)) * 170%); }
.twinkle { position: absolute; inset: 0; animation: twinkle 2.6s ease-in-out infinite alternate;
  background: radial-gradient(1.5px 1.5px at 24% 40%, #fff 50%, transparent 51%), radial-gradient(1.5px 1.5px at 40% 74%, #fff 50%, transparent 51%), radial-gradient(1px 1px at 80% 62%, #fff 50%, transparent 51%); }
@keyframes twinkle { from { opacity: 0.2; } to { opacity: 1; } }
.s-garland { left: 71%; top: 2%; width: 30%; --drop: 300ms; --amp: 1.6deg; --swing: 6s; }
.s-rug     { --x: 46; --b: 99; --w: 62; --d: 100; scale: 1 0.5; }
.lamp-glow { position: absolute; left: 9%; top: 71%; width: 46%; aspect-ratio: 1; translate: -50% -50%; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 214, 150, 0.42), rgba(255, 214, 150, 0)); animation: glow 4.5s ease-in-out infinite alternate; }
@keyframes glow { from { opacity: 0.6; } to { opacity: 1; } }
.s-lamp    { --x: 9;  --b: 93; --w: 12; --d: 160; }
.s-crib    { --x: 46; --b: 93; --w: 54; --d: 220; }
.s-bunny   { --x: 21; --b: 99; --w: 8;  --d: 320; }
.s-mobile  { left: 46%; top: 2%; width: 20%; --drop: 700ms; }

.signup { display: flex; gap: 10px; flex-wrap: wrap; }
.signup input { flex: 1 1 220px; min-height: 50px; border-radius: 999px; border: 1px solid rgba(201, 207, 224, 0.35);
  background: rgba(255, 255, 255, 0.06); color: #fff; padding: 0 20px; font: 400 1rem var(--sans); }
.signup input::placeholder { color: rgba(201, 207, 224, 0.75); }
.signup .button { border: 0; -webkit-appearance: none; appearance: none; cursor: pointer; }
.signup .button:disabled { opacity: 0.7; cursor: default; }
.signup-trap { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.signup-note { flex-basis: 100%; margin: 4px 0 0; min-height: 1.4em; color: var(--moon-text); font-size: 0.9375rem; }
.button--light { background: #fff; color: var(--ink); box-shadow: none; }
.button--light:hover { background: #eef0f6; }


/* ---------- motion versions: html[data-motion] is "a" (Veo loops for the feeding and the birds) or "b" (Veo birds, and
   the feeding arm moves with CSS). ?motion=a or ?motion=b picks one; js/canvas.js loads the videos. ---------- */
.live-host > img { display: block; width: 100%; height: auto; }
.bird.live-host > img { position: absolute; }
/* each video's box is the piece's box plus the room the motion needs (assets/live/boxes.json, from tools/live.py) */
.live { position: absolute; display: block; max-width: none; pointer-events: none; opacity: 0; transition: opacity 280ms ease;
  left: var(--lx); top: var(--ly); width: var(--lw); height: var(--lh); }
.live-box { position: absolute; left: var(--lx); top: var(--ly); width: var(--lw); height: var(--lh); pointer-events: none; }
.live-box > .live { left: 0; top: 0; width: 100%; height: 100%; }
.is-live > .live { opacity: 1; }
.live-host.is-live > img { visibility: hidden; transition: visibility 0s 280ms; }
.live-gone { visibility: hidden !important; transition: visibility 0s 280ms; }
.live-bird   { --lx: -28%; --ly: -19.993%; --lw: 156%; --lh: 140.041%; }
.live-taste  { --lx: 22.9%; --ly: 35.233%; --lw: 76.541%; --lh: 66.352%; }
/* character motion with CSS: the family and mother breathe and rock, the baby bounces with a little squash, and the birds
   bob with each flap. The spoon's arc and the chewing run in version A only until its video takes over. */
.h-family { --idle: breathe 6.8s linear calc(var(--d, 0) * 1ms + 1100ms) infinite; }
.t-parent { --idle: breathe 7.6s linear calc(var(--d, 0) * 1ms + 1100ms) infinite; }
.t-baby { --idle: bounce 3.2s linear calc(var(--d, 0) * 1ms + 1100ms) infinite; }
.bird img { animation-name: wings-a, wingbob; animation-duration: 400ms, 400ms; animation-timing-function: step-end, cubic-bezier(0.37, 0, 0.63, 1); animation-iteration-count: infinite, infinite; }
.bird img:last-child { animation-name: wings-b, wingbob; }
.is-up .k-spoon { animation: spoon-in 900ms cubic-bezier(0.25, 0.8, 0.3, 1) 900ms both, feed-arc 3.6s linear 1800ms infinite; }
.chomp { --idle: chew 3.6s linear 1800ms infinite; }
@keyframes breathe {
  0% { transform: none; animation-timing-function: cubic-bezier(0.61, 1, 0.88, 1); }
  25% { transform: rotate(-0.9deg) scale(1.003, 1.008); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  75% { transform: rotate(0.9deg) scale(1.006, 1.016); animation-timing-function: cubic-bezier(0.12, 0, 0.39, 0); }
  100% { transform: none; }
}
@keyframes bounce {
  0% { transform: none; animation-timing-function: cubic-bezier(0.61, 1, 0.88, 1); }
  25% { transform: translateY(-6%) rotate(-2deg) scale(0.99, 1.01); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  75% { transform: translateY(0.5%) rotate(0.5deg) scale(1.02, 0.98); animation-timing-function: cubic-bezier(0.12, 0, 0.39, 0); }
  100% { transform: none; }
}
@keyframes wingbob { 0% { translate: 0 -56%; } 50% { translate: 0 -44%; } 100% { translate: 0 -56%; } }
/* the spoon travels on a gentle arc, pauses at the mouth, and arcs back */
@keyframes feed-arc {
  0% { transform: translate(22%, 10%) rotate(5deg); animation-timing-function: cubic-bezier(0.45, 0, 0.55, 1); }
  10% { transform: translate(22%, 10%) rotate(5deg); animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1); }
  26% { transform: translate(10%, -2%) rotate(1deg); animation-timing-function: cubic-bezier(0.3, 0, 0.4, 1); }
  42% { transform: translate(0, 0) rotate(0deg); }
  60% { transform: translate(0, 0) rotate(0deg); animation-timing-function: cubic-bezier(0.45, 0, 0.55, 1); }
  76% { transform: translate(11%, -1%) rotate(2deg); animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1); }
  92%, 100% { transform: translate(22%, 10%) rotate(5deg); }
}

/* version B: the arm rests over the baby's bowl, dips in and scoops, lifts the spoon on an arc and brings it down to the
   mouth, waits while the baby takes the bite (the food stays behind), slides out with the wrist tipping up, and sinks
   back to the bowl. The shoulder turns (rotate), the arm reaches (transform), and the wrist turns, each easing on its
   own, so the spoon's path is a smooth curve. Poses come from tools/arm_rig.py. */
[data-motion="b"] .is-up .k-arm { animation: arm-in 900ms cubic-bezier(0.25, 0.8, 0.3, 1) 900ms both,
  arm-reach 4.8s linear 1800ms infinite, arm-turn 4.8s linear 1800ms infinite; }
[data-motion="b"] .is-up .arm-hand { animation: wrist 4.8s linear 1800ms infinite backwards; }
[data-motion="b"] .is-up .arm-food { animation: food 4.8s linear 1800ms infinite backwards; }
[data-motion="b"] .chomp { --idle: bite 4.8s linear 1800ms infinite; }
@keyframes arm-in { from { opacity: 0; transform: translate(16%, 6%); rotate: -9deg; } to { opacity: 1; transform: translate(-0.94%, 0.36%); rotate: -3.8deg; } }
@keyframes arm-reach {
  0% { transform: translate(-0.94%, 0.36%); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  7% { transform: translate(-4.58%, 2.74%); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  15% { transform: translate(-1.67%, 0.55%); animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1); }
  32% { transform: translate(7.42%, -2.78%); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  40% { transform: translate(2.33%, -1.11%); animation-timing-function: cubic-bezier(0.3, 0, 0.5, 1); }
  45%, 58% { transform: translate(0, 0); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  66% { transform: translate(3.31%, -1.09%); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  80% { transform: translate(2.23%, -1.09%); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  92%, 100% { transform: translate(-0.94%, 0.36%); }
}
@keyframes arm-turn {
  0% { rotate: -3.8deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  7% { rotate: -2.8deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  15% { rotate: -6.6deg; animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1); }
  32% { rotate: -1.1deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  40% { rotate: -0.5deg; animation-timing-function: cubic-bezier(0.3, 0, 0.5, 1); }
  45%, 58% { rotate: 0deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  66% { rotate: -2deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  80% { rotate: -2.6deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  92%, 100% { rotate: -3.8deg; }
}
@keyframes wrist {
  0% { rotate: -4deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  7% { rotate: -10deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  15% { rotate: 3deg; animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1); }
  32% { rotate: 4deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  40% { rotate: 1.5deg; animation-timing-function: cubic-bezier(0.3, 0, 0.5, 1); }
  45%, 58% { rotate: 0deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  66% { rotate: 8deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  80% { rotate: -1deg; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  92%, 100% { rotate: -4deg; }
}
/* the spoon arrives empty, picks the food up in the bowl, and leaves it in the baby's mouth */
@keyframes food { 0%, 6% { opacity: 0; } 9%, 58% { opacity: 1; } 62%, 100% { opacity: 0; } }
/* the baby leans toward the spoon from the feet, closes on it, then chews with a small bob of the head */
@keyframes bite {
  0%, 28% { transform: none; animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  40% { transform: rotate(1.8deg); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  45%, 58% { transform: rotate(1.5deg) scale(1.006, 0.994); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  66% { transform: rotate(-0.4deg); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  70% { transform: scale(1, 1.012); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  75% { transform: scale(1, 0.996); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  80% { transform: scale(1, 1.01); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  85% { transform: scale(1, 0.998); animation-timing-function: cubic-bezier(0.37, 0, 0.63, 1); }
  90%, 100% { transform: none; }
}

/* ---------- which app, when: an age line from birth to 2 years, one felt strip per app ---------- */
.ages { background: #151d33; color: #fff; padding: 24px max(clamp(24px, 6vw, 96px), calc((100% - 1280px) / 2 + 96px)) 88px; }
.ages h2 { margin: 0 0 10px; font: 500 clamp(2rem, 3.6vw, 3rem)/1.05 var(--serif); letter-spacing: -0.02em; }
.ages-lede { margin: 0 0 30px; max-width: 36rem; color: var(--moon-text); }
.timeline { --name: 210px; display: grid; gap: 14px; }
.axis { position: relative; height: 20px; margin: 0 26px 0 calc(var(--name) + 50px); font-size: 0.8125rem; color: var(--moon-text); }
.axis span { position: absolute; left: calc(var(--at) / 24 * 100%); translate: -50% 0; white-space: nowrap; }
.axis span:first-child { translate: 0 0; }
.axis span:last-child { translate: -100% 0; }
.lane { display: grid; grid-template-columns: var(--name) minmax(0, 1fr); column-gap: 24px; row-gap: 16px; align-items: center;
  padding: 22px 26px; border-radius: 22px; background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(201, 207, 224, 0.14); }
.lane-name { display: flex; align-items: center; gap: 12px; }
.lane-name img { width: 44px; height: 44px; border-radius: 22.5%; box-shadow: 0 6px 16px -8px rgba(0, 0, 0, 0.6); }
.lane-name h3 { margin: 0; font: 600 1.0625rem/1.2 var(--sans); }
.lane-name p { margin: 2px 0 0; font-size: 0.875rem; color: var(--moon-text); }
.track { position: relative; height: 26px; }
.track::before { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 2px; translate: 0 -50%; border-radius: 2px; background: rgba(201, 207, 224, 0.2); }
/* a felt strip: grain, a soft lower edge, and a running stitch */
.band { position: absolute; top: 0; bottom: 0; left: calc(var(--from) / 24 * 100%); width: calc((var(--to) - var(--from)) / 24 * 100%);
  border-radius: 999px; background: var(--grain), var(--lane); background-size: 160px 160px, auto;
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.14); outline: 1.5px dashed rgba(255, 255, 255, 0.6); outline-offset: -6px; }
.band--soft { opacity: 0.45; border-radius: 999px 0 0 999px; }
.band--soft + .band { border-radius: 0 999px 999px 0; }
.dot { position: absolute; top: 50%; left: calc(var(--at) / 24 * 100%); width: 14px; height: 14px; translate: -50% -50%; border-radius: 50%;
  background: #fff; box-shadow: 0 0 0 3px var(--lane-ink), 0 2px 6px rgba(0, 0, 0, 0.4); }
.marks { grid-column: 2; list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.marks li { font-size: 0.9375rem; line-height: 1.45; color: var(--moon-text); }
.marks strong { display: block; margin-bottom: 2px; color: #fff; font-weight: 600; }
.lane--sleep { --lane: linear-gradient(90deg, #b3aef0, #8f8ad8); --lane-ink: #8f8ad8; }
.lane--talk  { --lane: linear-gradient(90deg, #a9c0f2, #7393dc); --lane-ink: #7393dc; }
.lane--taste { --lane: linear-gradient(90deg, #f5dc93, #e8c262); --lane-ink: #e2b84a; }

/* ---------- phones and tall screens ---------- */
@media (orientation: portrait) {
  .canvas-hero .obj { --unit: min(1vw, 0.46svh); }
  .h-sky     { --b: 64; }
  .h-sun     { --x: 88; --b: 12.5; --w: 13; }
  .h-cloud1  { --x: 72; --b: 10;  --w: 20; }
  .h-cloud2  { --x: 12; --b: 53;  --w: 17; }
  .h-far     { --b: 70; --w: 260; }
  .h-round   { --x: 9;  --b: 66; --w: 24; }
  .h-mid     { --b: 94; --w: 220; }
  .h-cottage { --x: 31; --b: 76; --w: 56; }
  .h-apple   { --x: 78; --b: 74; --w: 44; }
  .h-family  { --x: 56; --b: 93; --w: 52; }
  /* the meadow always runs past the bottom edge, so scrolling never shows what stands behind it */
  .h-meadow  { --b: 106; --w: 300; }
}
@media (max-width: 760px) {
  .app { grid-template-columns: 1fr; padding: 48px 24px 28px; gap: 32px; }
  .app--flip .app-art { order: 0; }
  .app-art { margin: 0 4% 9% 0; }
  .phone { width: 27%; }
  .timeline { --name: 0px; }
  .axis { margin: 0 18px; }
  .lane { grid-template-columns: minmax(0, 1fr); padding: 18px; }
  .marks { grid-column: 1; grid-template-columns: 1fr; gap: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .stand, .js .stand, .is-up .stand, .k-spoon, .is-up .k-spoon, .k-arm, .is-up .k-arm, .arm-hand, .arm-food, .bird, .is-up .bird, .hang, .js .hang, .is-up .hang,
  .twinkle, .lamp-glow { animation: none !important; rotate: none; opacity: 1; transform: none; }
  .live { display: none; }
  .bird { display: none; }
  .js .hang { translate: -50% 0; }
}

