/* feltandcotton.com motion (BRIEF-248, ADR-175; Adam's picks 11 Oct 2026, R-WEBSITE-MOTION-PICKS).
   Every rule waits for html[data-motion="on"], which motion.js sets unless the visitor prefers reduced
   motion; without it (or without JS) the page is v1's static visuals. */

/* ---------- 1. Page background on scroll ---------- */
/* "Hero stays teal background, page background changes colour on scroll": magenta -> white -> grey. The hero
   keeps its own teal; About, Latest, the hosts and Segments are transparent over one page colour. Latest,
   then the hosts, crossing a line 60% down the window (at most 540px) pick the colour; the change is an
   opacity fade of fixed white and grey layers over the magenta page (composited: a background-colour fade
   repaints the whole page every frame, which Adam saw as a glitch). Text switches once per change between
   the dark-page set (v1's About colours) and the light-page set (v1's colours elsewhere), with the fade. */
html[data-motion="on"] body {
  background: var(--magenta);
}
html[data-motion="on"] body::before,
html[data-motion="on"] body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
  will-change: opacity;
}
html[data-motion="on"] body::before {
  background: var(--white);
}
html[data-motion="on"] body::after {
  background: var(--cotton);
}
html[data-motion="on"][data-page-bg="white"] body::before,
html[data-motion="on"][data-page-bg="cotton"] body::before,
html[data-motion="on"][data-page-bg="cotton"] body::after {
  opacity: 1;
}
html[data-motion="on"] :is(.about, .episodes, .hosts, .segments) {
  background: transparent;
}
html[data-motion="on"] :is(.about__heading, .about__body, .section-heading, .host__name, .host__bio) {
  transition: color 0.5s ease;
}
html[data-motion="on"][data-page="dark"] .about__heading,
html[data-motion="on"][data-page="dark"] .section-heading,
html[data-motion="on"][data-page="dark"] :is(.host__name, .host__bio) {
  color: var(--white);
}
html[data-motion="on"][data-page="dark"] .about__body {
  color: var(--cotton);
}
html[data-motion="on"][data-page="light"] .about__heading {
  color: var(--magenta);
}
html[data-motion="on"][data-page="light"] .about__body {
  color: var(--black);
}

/* ---------- 2. Fluid puppet positions ---------- */
/* The gap between the two puppets' inner edges, piecewise linear through Figma's exact values:
   LAUNCH 18px @390, 127px @768, 440px @1440 (held below 390 and above 1440), with a knot at 1024
   (320px) where the tagline steps up to 40px; SOON -148px @390 and @768, 0 @1440. At 1440/768/390 the
   positions equal v1's; no puppet touches the wordmark, tagline or a listen button from 320 to 2560.
   The hero is the container with its padding added back (Figma's frame widths are the page width); not
   <body>, whose containment would make it the containing block of the fixed page-colour layers. */
html[data-motion="on"] .hero {
  container-type: inline-size;
  --page-w: calc(100cqw + 2 * var(--pad-x));
}
html[data-motion="on"] .hero__stage {
  position: relative;
  display: block;
  --gap: clamp(18px, max(calc(18px + (var(--page-w) - 390px) * 0.288360),
    min(calc(127px + (var(--page-w) - 768px) * 0.753906), calc(320px + (var(--page-w) - 1024px) * 0.288462))), 440px);
}
html[data-motion="on"] .is-soon .hero__stage {
  --gap: clamp(-148px, calc(-148px + (var(--page-w) - 768px) * 0.220238), 0px);
}
html[data-motion="on"] .puppet--hero {
  position: absolute;
  bottom: 0;
  margin: 0 !important;
}
html[data-motion="on"] .is-soon .puppet--hero {
  bottom: -40px;
}
html[data-motion="on"] .puppet--hero.puppet--felt {
  right: calc(50% + var(--gap) / 2);
}
html[data-motion="on"] .puppet--hero.puppet--cotton {
  left: calc(50% + var(--gap) / 2);
}
html[data-motion="on"] .listen-row {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: max(var(--gap), 210px);
  margin: 0 !important;
  flex-direction: row;
  flex-wrap: wrap;
  align-content: center;
  justify-content: center;
}
@media (max-width: 639px) {
  html[data-motion="on"] .is-soon .puppet--hero {
    bottom: 0;
  }
}

/* ---------- 3. Hero doodles: boil + tiles ---------- */
/* Figma's composition is the centre tile; the scattered side tiles show only beyond 1440 px (the outer
   pair beyond 2880 px). Each doodle boils on its own phase (four drawings at ~10 fps, transforms only),
   paused while the hero is off-screen. While animating, no colour-dodge group: animated layers inside it
   drew dark fringes in some browsers, and dodging pure white gives white, so the look is the same. */
.doodle-tile:not([data-tile="0"]) {
  display: none;
}
@media (min-width: 1441px) {
  html[data-motion="on"] .doodle-tile[data-tile="-1"],
  html[data-motion="on"] .doodle-tile[data-tile="1"] {
    display: block;
  }
}
@media (min-width: 2881px) {
  html[data-motion="on"] .doodle-tile[data-tile="-2"],
  html[data-motion="on"] .doodle-tile[data-tile="2"] {
    display: block;
  }
}
html[data-motion="on"] .hero__doodles {
  mix-blend-mode: normal;
}
html[data-motion="on"] .doodle {
  animation: felt-boil var(--bd) steps(1, end) var(--bl) infinite;
}
html.hero-offscreen .doodle {
  animation-play-state: paused;
}
@keyframes felt-boil {
  0% {
    transform: translate(0, 0) rotate(0deg);
  }
  25% {
    transform: translate(1px, -1px) rotate(0.6deg);
  }
  50% {
    transform: translate(-1px, 0.5px) rotate(-0.5deg);
  }
  75% {
    transform: translate(0.5px, 1px) rotate(0.3deg);
  }
}

/* ---------- 4. Bio-circle idles ---------- */
.idle {
  position: absolute;
  inset: 0;
}
.idle > * {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (prefers-reduced-motion: reduce) {
  .doodle {
    animation: none !important;
  }
}
