/* Spindoodle's page: warm paper, the app icon's coral-to-plum gradient, and everything cut out
   like the app's stickers, with a white die-cut edge. The accent is the app's AccentColor
   (#e84a6b); the buddies are the app's own sprite strips (64 x 64, eight frames at 8 fps). */

:root {
  color-scheme: light;

  --paper: #fff6f1;
  --paper-deep: #fbe9e4;
  --ink: #2d1633;
  --text: #4a3550;
  --dim: #7b6680;
  --coral: #e84a6b;      /* the app's accent */
  --peach: #ff7a6e;      /* the icon's top-left */
  --plum: #7a34a0;       /* the icon's bottom-right */
  --line: rgb(122 52 160 / 0.14);
  --gradient: linear-gradient(135deg, var(--peach), #d0507f 50%, var(--plum));
  --lift: 0 18px 40px -18px rgb(122 52 160 / 0.45);

  --round: "Fredoka", "Nunito", system-ui, sans-serif;
  --body: "Nunito", system-ui, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }

html { background: var(--paper); }

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font-family: var(--body);
  font-size: 1.125rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img, video { display: block; max-width: 100%; height: auto; }

p { margin: 0; }

a {
  color: var(--coral);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

a:hover { color: var(--plum); }

:focus-visible {
  outline: 3px solid var(--plum);
  outline-offset: 3px;
}

h1, h2, h3 {
  margin: 0;
  font-family: var(--round);
  color: var(--ink);
  text-wrap: balance;
}

h2 {
  font-size: clamp(30px, 4.6vw, 48px);
  font-weight: 600;
  line-height: 1.12;
}

h3 {
  font-size: 21px;
  font-weight: 600;
  line-height: 1.25;
}

/* ---------- Buddies and sprinkles ---------- */

/* A buddy is its strip of eight 64 x 64 frames, played at the app's 8 fps, with a white sticker edge. */
.buddy {
  --s: 1.5px;
  display: block;
  width: calc(64 * var(--s));
  height: calc(64 * var(--s));
  background: no-repeat 0 0 / calc(512 * var(--s)) calc(64 * var(--s));
  image-rendering: pixelated;
  filter: drop-shadow(2px 0 0 #fff) drop-shadow(-2px 0 0 #fff) drop-shadow(0 2px 0 #fff) drop-shadow(0 -2px 0 #fff)
    drop-shadow(0 6px 8px rgb(122 52 160 / 0.25));
}

/* A sprinkle is a cell of the app's effects sheet: sparkle, heart, leaf or bubble across, four phases down. */
.sprinkle {
  --s: 2px;
  --column: 0;
  position: absolute;
  width: calc(32 * var(--s));
  height: calc(32 * var(--s));
  background: url("/spindoodle/img/effects.png") no-repeat calc(var(--column) * -32 * var(--s)) 0 / calc(128 * var(--s)) calc(128 * var(--s));
  image-rendering: pixelated;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .buddy { animation: frames 1s steps(8) infinite; }
  .sprinkle { animation: twinkle 0.5s steps(4) infinite; }
}

@keyframes frames { to { background-position-x: calc(-512 * var(--s)); } }
@keyframes twinkle { to { background-position-y: calc(-128 * var(--s)); } }

/* ---------- Hero ---------- */

.hero {
  position: relative;
  display: grid;
  gap: 40px;
  max-width: 1136px;
  margin: 0 auto;
  padding: clamp(32px, 6vw, 72px) 16px 0;
  overflow: clip;
}

@media (min-width: 880px) {
  .hero { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); align-items: center; gap: 56px; }
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  font: 600 24px/1 var(--round);
  color: var(--coral);
}

.brand img {
  width: 52px;
  border-radius: 13px;
  box-shadow: var(--lift);
}

.hero h1 {
  margin-top: 24px;
  font-size: clamp(42px, 7.2vw, 80px);
  font-weight: 650;
  line-height: 1.02;
  letter-spacing: -0.01em;
}

.lede {
  max-width: 30em;
  margin-top: 22px;
  font-size: 1.25rem;
  line-height: 1.55;
}

.status {
  display: inline-block;
  margin-top: 28px;
  padding: 10px 20px 11px;
  font: 600 17px/1 var(--round);
  color: #fff;
  background: var(--gradient);
  border-radius: 999px;
  box-shadow: 0 0 0 4px #fff, var(--lift);
}

.feature { margin: 0; justify-self: center; }

.stage {
  position: relative;
  width: min(300px, 70vw);
  margin: 0 auto;
  padding: 0 0 0 0;
}

/* The gradient pooled behind the clip. */
.stage::before {
  content: "";
  position: absolute;
  inset: -12% -22%;
  z-index: -2;
  background: radial-gradient(closest-side, rgb(255 122 110 / 0.35), rgb(122 52 160 / 0.16) 60%, transparent);
}

/* A clip is a 9:16 video with a white sticker edge. */
.reel {
  position: relative;
  z-index: 1;
  overflow: hidden;
  aspect-ratio: 9 / 16;
  background: #3b2a12;
  border: 8px solid #fff;
  border-radius: 30px;
  box-shadow: var(--lift), 0 2px 0 rgb(122 52 160 / 0.08);
}

.reel video { width: 100%; height: 100%; object-fit: cover; }

.feature .reel { rotate: 2deg; }

/* Plays the top clip with the app's music; the speaker shows a cross until it's on. */
.sound {
  position: absolute;
  top: 12px;
  right: 12px;
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 0 14px 0 10px;
  border: 0;
  border-radius: 999px;
  background: rgb(255 255 255 / 0.92);
  color: var(--ink);
  font: 600 0.9rem/1 var(--round);
  box-shadow: 0 4px 14px rgb(45 22 51 / 0.25);
  cursor: pointer;
}

.sound:hover { color: var(--plum); }

.sound svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sound .speaker { fill: currentColor; }
.sound .waves { display: none; }
.sound[aria-pressed="true"] .waves { display: inline; }
.sound[aria-pressed="true"] .mute { display: none; }

/* The fox peeks out from behind the clip, as buddies peek from behind products in the videos. */
.peeker {
  --s: 2px;
  position: absolute;
  top: 18%;
  right: 6%;
  z-index: 0;
  translate: 62% 0;
}

@media (prefers-reduced-motion: no-preference) {
  .peeker { animation: frames 1s steps(8) infinite, peek 4.8s cubic-bezier(0.34, 1.56, 0.64, 1) infinite; }
}

@keyframes peek {
  0%, 12% { translate: 0 0; }
  26%, 70% { translate: 62% 0; }
  84%, 100% { translate: 0 0; }
}

.s1 { top: 4%; left: -12%; --column: 0; }
.s2 { bottom: 14%; right: -14%; --column: 1; animation-delay: -0.2s; }
.s3 { bottom: -4%; left: 8%; --column: 0; --s: 1.5px; animation-delay: -0.35s; }

.feature figcaption {
  margin-top: 20px;
  color: var(--dim);
  font-size: 1rem;
  text-align: center;
}

/* ---------- Sections ---------- */

main { padding: 0 16px clamp(72px, 9vw, 120px); }

main > section {
  max-width: 1104px;
  margin: clamp(88px, 12vw, 150px) auto 0;
}

.section-lede {
  max-width: 36em;
  margin-top: 20px;
  font-size: 1.1875rem;
}

.note {
  max-width: 40em;
  margin-top: 28px;
  color: var(--dim);
  font-size: 1rem;
}

/* How it works */

.how {
  display: grid;
  gap: 48px;
}

@media (min-width: 900px) {
  .how { grid-template-columns: minmax(0, 7fr) minmax(0, 4fr); gap: 64px; align-items: center; }
}

.steps {
  margin: 36px 0 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}

.steps li {
  position: relative;
  padding: 0 0 26px 68px;
  counter-increment: step;
}

.steps li + li { margin-top: 2px; }

/* Each number on a gradient sticker, joined to the next by a dotted thread. */
.steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: -4px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  font: 600 21px/1 var(--round);
  color: #fff;
  background: var(--gradient);
  border-radius: 50%;
  box-shadow: 0 0 0 4px #fff, var(--lift);
}

.steps li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 21px;
  top: 50px;
  bottom: 4px;
  border-left: 3px dotted rgb(232 74 107 / 0.4);
}

.steps h3 + p { margin-top: 6px; }

/* The first screen, as it sits on the phone, fading where the keyboard would rise. */
.phone {
  justify-self: center;
  width: min(300px, 76vw);
  margin: 0;
  padding: 10px 10px 0;
  background: #1d1420;
  border-radius: 46px 46px 0 0;
  box-shadow: var(--lift);
  -webkit-mask-image: linear-gradient(#000 78%, transparent);
  mask-image: linear-gradient(#000 78%, transparent);
}

.phone img { border-radius: 37px 37px 0 0; }

/* Styles */

.effects {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 36px 20px;
  margin: 44px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 880px) { .effects { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 28px; } }

.reel.small { border-width: 6px; border-radius: 22px; }

.effects li:nth-child(odd) .reel { rotate: -1.2deg; }
.effects li:nth-child(even) .reel { rotate: 1.2deg; }

.effects h3 { margin-top: 20px; }

.effects h3 + p { margin-top: 4px; font-size: 1rem; line-height: 1.45; }

.more-title { margin-top: 64px; }

.chips {
  display: grid;
  gap: 12px;
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 600px) { .chips { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 960px) { .chips { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.chips li {
  padding: 14px 18px 15px;
  font-size: 1rem;
  line-height: 1.45;
  background: #fff;
  border-radius: 18px;
  box-shadow: 0 0 0 1px var(--line), 0 8px 20px -14px rgb(122 52 160 / 0.4);
}

.chips strong {
  display: block;
  font: 600 18px/1.3 var(--round);
  color: var(--ink);
}

/* Buddies */

.buddies {
  position: relative;
  padding: clamp(32px, 5vw, 64px) clamp(16px, 4vw, 56px);
  background: linear-gradient(160deg, #fff, var(--paper-deep));
  border-radius: 40px;
  box-shadow: 0 0 0 1px var(--line);
}

.moves {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 32px 20px;
  margin: 44px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 880px) { .moves { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; } }

.moves h3 { margin-top: 18px; }
.moves h3 + p { margin-top: 4px; font-size: 1rem; line-height: 1.45; }

/* A small stage: the lifted product from the Product Pop clip, and a buddy doing one move.
   Sizes and paths are in container units, so the moves keep their shape at any width. */
.mini {
  position: relative;
  overflow: hidden;
  container-type: inline-size;
  aspect-ratio: 9 / 16;
  background: radial-gradient(circle at 50% 46%, #fff3d9, #f4c48a 55%, #c98b4e);
  border: 6px solid #fff;
  border-radius: 22px;
  box-shadow: var(--lift);
}

.mini .product {
  position: absolute;
  left: 50%;
  top: 48%;
  z-index: 2;
  width: 72%;
  translate: -50% -50%;
}

/* A buddy is about a third of the stage's width. */
.mini .buddy {
  --s: calc(100cqi / 215);
  position: absolute;
  left: 50%;
  top: 48%;
  z-index: 1;
  margin: calc(-32 * var(--s)) 0 0 calc(-32 * var(--s));
}

/* Without motion, each buddy waits where its move would show it. */
.mini[data-move="peek"] .buddy { translate: 30% -100%; }
.mini[data-move="fly"] .buddy { translate: -24cqi -48cqi; }
.mini[data-move="orbit"] .buddy { translate: 0 170%; z-index: 3; }
.mini[data-move="hop"] .buddy { translate: -90% 145%; z-index: 3; }

@media (prefers-reduced-motion: no-preference) {
  .mini[data-move="peek"] .buddy { animation: frames 1s steps(8) infinite, mini-peek 3.2s cubic-bezier(0.34, 1.56, 0.64, 1) infinite; }
  .mini[data-move="fly"] .buddy { animation: frames 1s steps(8) infinite, mini-fly 3.2s ease-in-out infinite; }
  .mini[data-move="orbit"] .buddy { animation: frames 1s steps(8) infinite, mini-orbit 3.2s linear infinite; }
  .mini[data-move="hop"] .buddy { animation: frames 1s steps(8) infinite, mini-hop 3.2s linear infinite; }
}

/* The fly-by's trail: two of the app's sparkles, a beat behind the bee. */
.mini .trail {
  --s: calc(100cqi / 280);
  left: 50%;
  top: 48%;
  z-index: 1;
  margin: calc(-16 * var(--s)) 0 0 calc(-16 * var(--s));
  display: none;
}

@media (prefers-reduced-motion: no-preference) {
  .mini .trail { display: block; animation: twinkle 0.5s steps(4) infinite, mini-fly 3.2s ease-in-out -3s infinite; }
  .mini .trail.late { --s: calc(100cqi / 360); animation-delay: -0.2s, -2.8s; }
}

/* Up from behind the top of the fan, its feet still hidden. */
@keyframes mini-peek {
  0%, 10% { translate: 30% -20%; }
  28%, 72% { translate: 30% -100%; }
  90%, 100% { translate: 30% -20%; }
}

/* In container units, so the trail's smaller sparkles can follow the same path. It
   crosses low behind the fan, showing over its top. */
@keyframes mini-fly {
  0% { translate: -70cqi 0; }
  70%, 100% { translate: 70cqi -50cqi; }
}

/* Round the product: behind it across the top, in front of it across the bottom. */
@keyframes mini-orbit {
  0% { translate: 128% 0; z-index: 1; }
  12.5% { translate: 90% -120%; z-index: 1; }
  25% { translate: 0 -170%; z-index: 1; }
  37.5% { translate: -90% -120%; z-index: 1; }
  50% { translate: -128% 0; z-index: 3; }
  62.5% { translate: -90% 120%; z-index: 3; }
  75% { translate: 0 170%; z-index: 3; }
  87.5% { translate: 90% 120%; z-index: 3; }
  100% { translate: 128% 0; z-index: 3; }
}

@keyframes mini-hop {
  0% { translate: -230% 145%; z-index: 3; }
  12% { translate: -190% 75%; }
  24% { translate: -150% 145%; }
  36% { translate: -120% 105%; }
  46%, 80% { translate: -90% 145%; }
  100% { translate: -230% 145%; }
}

/* The roster, filtered by collection as the app's category chips do. */
.collection { margin-top: 64px; }

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  border: 0;
}

.filters legend {
  float: left;
  margin: 0 6px 0 0;
  padding: 9px 0;
  font: 600 16px/1.2 var(--round);
  color: var(--dim);
}

.filters label {
  position: relative;
  padding: 8px 16px 9px;
  font: 500 16px/1.2 var(--round);
  color: var(--ink);
  background: #fff;
  border-radius: 999px;
  box-shadow: 0 0 0 1px var(--line);
  cursor: pointer;
}

.filters input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}

.filters label:hover { box-shadow: 0 0 0 2px rgb(232 74 107 / 0.5); }
.filters label:has(input:checked) { color: #fff; background: var(--gradient); box-shadow: none; }
.filters label:has(input:focus-visible) { outline: 3px solid var(--plum); outline-offset: 2px; }

.roster {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 18px 12px;
  margin: 28px 0 0;
  padding: 0;
  list-style: none;
  font: 500 15px/1.25 var(--round);
  color: var(--ink);
  text-align: center;
}

.roster .buddy { margin: 0 auto 6px; }

@media (max-width: 520px) {
  .roster { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px 4px; font-size: 12.5px; }
  .roster .buddy { --s: 1px; }
}

/* The strips don't all start together. */
.roster li:nth-child(3n + 1) .buddy { animation-delay: -0.25s; }
.roster li:nth-child(3n + 2) .buddy { animation-delay: -0.625s; }

.collection:has(input[value="woodland"]:checked) .roster li:not([data-collection="woodland"]),
.collection:has(input[value="waterside"]:checked) .roster li:not([data-collection="waterside"]),
.collection:has(input[value="fantasy"]:checked) .roster li:not([data-collection="fantasy"]),
.collection:has(input[value="cozy"]:checked) .roster li:not([data-collection="cozy"]),
.collection:has(input[value="accessories"]:checked) .roster li:not([data-collection="accessories"]),
.collection:has(input[value="garden"]:checked) .roster li:not([data-collection="garden"]),
.collection:has(input[value="sewing"]:checked) .roster li:not([data-collection="sewing"]) { display: none; }

.makers {
  display: grid;
  gap: 20px;
  margin-top: 56px;
}

@media (min-width: 760px) { .makers { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.maker {
  padding: 24px 26px 26px;
  background: #fff;
  border-radius: 24px;
  box-shadow: 0 0 0 1px var(--line), var(--lift);
}

.maker h3 + p { margin-top: 8px; font-size: 1.0625rem; }

/* The doodle card gets a wobbly, hand-drawn outline in colored pencil. */
.maker.doodle {
  border: 2.5px solid rgb(232 74 107 / 0.7);
  border-radius: 28px 10px 24px 12px / 12px 26px 10px 28px;
  box-shadow: 3px 4px 0 rgb(122 52 160 / 0.18);
}

/* Words, music and a nudge */

.cards {
  display: grid;
  gap: 20px;
  margin: 40px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 860px) { .cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.cards li {
  padding: 24px 26px 26px;
  background: #fff;
  border-radius: 24px;
  box-shadow: 0 0 0 1px var(--line), var(--lift);
}

.cards h3 + p { margin-top: 8px; font-size: 1.0625rem; }

/* Made on your phone */

.yours {
  display: grid;
  gap: 40px;
}

@media (min-width: 900px) {
  .yours { grid-template-columns: minmax(0, 7fr) minmax(0, 4fr); gap: 56px; align-items: center; }
}

.yours .copy p { max-width: 34em; }
.yours h2 + p { margin-top: 20px; }
.yours p + p { margin-top: 1em; }

.cheer {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.cheer .buddy { --s: 1.4px; }

@media (max-width: 480px) { .cheer .buddy { --s: 1.1px; } }
.cheer li:nth-child(even) .buddy { animation-delay: -0.5s; }

/* The close */

.last {
  text-align: center;
}

.last .icon {
  width: 132px;
  margin: 0 auto 28px;
  border-radius: 30px;
  box-shadow: 0 0 0 6px #fff, var(--lift);
}

.last .status { margin-top: 24px; }

/* ---------- Footer ---------- */

.footer {
  padding: 28px 16px 40px;
  border-top: 2px dotted rgb(232 74 107 / 0.35);
  color: var(--dim);
  font-size: 1rem;
  text-align: center;
}

.footer p + p { margin-top: 0.3em; }
.footer a { color: var(--text); }
