/*
 * Alexander — "felt and construction paper".
 *
 * Daylight, not night. A sticker book: cut-paper shapes, thick outlines,
 * nothing sharp, no grey shadows. He cannot read, so nothing here depends on
 * reading: the picture is the content and the speaker button says it aloud.
 */

:root {
  --daylight: #FFF6E4;
  --pumpkin:  #FF9B54;
  --grape:    #8E7CC3;
  --mint:     #A8DCC4;
  --cocoa:    #4A3B2F;
  /* extra papers, used as card grounds so repeated shapes stay distinct */
  --sky:      #BFE3F2;
  --butter:   #FFE7B0;
  --blush:    #FFC9C9;
  --focus:    var(--grape);

  --round: "Nunito", "Quicksand", "Varela Round", "Trebuchet MS", system-ui, sans-serif;
  --edge: 4px;
}

body {
  background: var(--daylight);
  color: var(--cocoa);
  font-family: var(--round);
  font-size: 24px;
  font-weight: 700;
  line-height: 1.3;
  padding-bottom: 3rem;
}

/* torn-paper strip across the top */
body::before {
  content: ""; display: block; height: 14px;
  background: repeating-linear-gradient(90deg,
    var(--pumpkin) 0 24px, var(--grape) 24px 48px, var(--mint) 48px 72px);
}

.top {
  padding: 1rem 1rem .25rem;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}
.top h1 {
  margin: 0; font-size: 1.5rem; font-weight: 800; color: var(--cocoa);
  letter-spacing: -.01em;
}

/* ---------- the Boo button ---------- */

.boo-zone {
  position: relative; display: grid; place-items: center;
  padding: .5rem 1rem 1.75rem; overflow: hidden;
}
.boo {
  width: min(56vw, 220px); aspect-ratio: 1; border-radius: 50%;
  background: var(--pumpkin); color: var(--cocoa);
  border: var(--edge) solid var(--cocoa);
  box-shadow: 0 10px 0 var(--cocoa);      /* flat paper edge, never a grey blur */
  font-family: var(--round); font-weight: 800; font-size: clamp(2.6rem, 12vw, 4rem);
  letter-spacing: .02em; display: grid; place-content: center;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.boo:active { transform: translateY(8px); box-shadow: 0 2px 0 var(--cocoa); }
@media (prefers-reduced-motion: no-preference) {
  .boo { transition: transform .09s ease, box-shadow .09s ease; }
}

/* the ghost that flies out of the button */
.swoop {
  position: absolute; left: 50%; top: 55%; width: 120px; margin-left: -60px;
  pointer-events: none; opacity: 0;
}
.swoop svg { fill: #FFFFFF; stroke: var(--cocoa); stroke-width: 4; stroke-linejoin: round; }
.swoop .feat { fill: var(--cocoa); stroke: none; }
@media (prefers-reduced-motion: no-preference) {
  .swoop.go { animation: swoop 2.3s cubic-bezier(.3,.7,.4,1) forwards; }
}
@media (prefers-reduced-motion: reduce) {
  .swoop.go { animation: appear 2.3s ease forwards; }
}
/* Times out with the Boo sound: rises, hangs and wobbles, then drifts off. */
@keyframes swoop {
  0%   { opacity: 0; transform: translateY(34px) scale(.4) rotate(-6deg); }
  14%  { opacity: 1; transform: translateY(-8px) scale(1.08) rotate(5deg); }
  32%  { opacity: 1; transform: translateY(-52px) scale(1) rotate(-6deg); }
  50%  { opacity: 1; transform: translateY(-78px) scale(1.04) rotate(5deg); }
  68%  { opacity: 1; transform: translateY(-104px) scale(1) rotate(-4deg); }
  100% { opacity: 0; transform: translateY(-220px) scale(.86) rotate(7deg); }
}
@keyframes appear { 0% { opacity: 0 } 15% { opacity: 1 } 85% { opacity: 1 } 100% { opacity: 0 } }

/* ---------- the sticker sheet ---------- */

.sheet {
  display: grid; gap: 1.25rem; padding: 0 1rem;
  grid-template-columns: 1fr;
}
@media (min-width: 480px) { .sheet { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px) { .sheet { grid-template-columns: repeat(3, 1fr); } }

.thing {
  background: #FFFFFF; border: var(--edge) solid var(--cocoa); border-radius: 22px;
  box-shadow: 8px 8px 0 var(--grape);
  overflow: hidden; display: flex; flex-direction: column;
}
.thing:nth-child(3n+2) { box-shadow: 8px 8px 0 var(--pumpkin); }
.thing:nth-child(3n+3) { box-shadow: 8px 8px 0 var(--mint); }

/* The picture is the card; everything else is a caption under it. Fill and
   stroke live on the <svg> so paths, ellipses and circles all inherit them. */
.thing .art {
  width: 100%; aspect-ratio: 5 / 4; background: var(--ground);
  fill: var(--shape); stroke: var(--cocoa); stroke-width: 4; stroke-linejoin: round;
}
.thing .art .feat { fill: var(--feat); stroke: none; }
.thing .art .feat-stroke { fill: none; stroke: var(--cocoa); stroke-width: 5; stroke-linecap: round; }
.thing .art .teeth { stroke: var(--shape); stroke-width: 4; fill: none; }

/* The whole picture is a button: the biggest, most obvious thing to press. */
.poke {
  display: block; width: 100%; padding: 0; background: none; border: 0;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.thing.play { border-color: var(--grape); }
@media (prefers-reduced-motion: no-preference) {
  .thing { transition: transform .12s ease; }
  .thing.play { transform: scale(1.015); }
}

.thing .caption {
  display: flex; align-items: center; gap: .75rem;
  padding: .85rem 1rem; border-top: var(--edge) solid var(--cocoa);
}
.thing .words {
  font-size: clamp(1.4rem, 6vw, 1.9rem); font-weight: 800; line-height: 1.1;
  flex: 1 1 auto;
}

.speak {
  flex: 0 0 64px; width: 64px; height: 64px; border-radius: 50%;
  background: var(--mint); border: var(--edge) solid var(--cocoa);
  display: grid; place-content: center; touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.speak svg { width: 30px; height: 30px; fill: var(--cocoa); }
.speak[aria-pressed="true"] { background: var(--grape); }
.speak:active { transform: scale(.92); }
@media (prefers-reduced-motion: no-preference) {
  .speak { transition: transform .1s ease, background .15s ease; }
}

/* ---------- states ---------- */

.note {
  margin: 2rem 1rem; padding: 1.5rem; text-align: center;
  border: var(--edge) dashed var(--cocoa); border-radius: 22px;
  font-size: 1.2rem;
}


/* ------------------------------------------------------------------ motion
 *
 * Every motif has a loop that suits it. They are defined always but held at
 * animation-play-state: paused, so the first keyframe is the resting pose and
 * hovering or pressing simply lets them run. base.css already flattens all of
 * this under prefers-reduced-motion.
 */

.art [class], .art .bulbs path { transform-box: fill-box; }

.art .float   { animation: a-float 1.5s ease-in-out infinite; transform-origin: 50% 50%; }
.art .squash  { animation: a-squash 1.1s ease-in-out infinite; transform-origin: 50% 100%; }
.art .rock    { animation: a-rock 2.2s ease-in-out infinite; transform-origin: 50% 100%; }
.art .tail    { animation: a-swish 1.3s ease-in-out infinite; transform-origin: 10% 5%; }
.art .tilt    { animation: a-tilt 2.4s ease-in-out infinite; transform-origin: 50% 90%; }
.art .wing-l  { animation: a-flap-l .42s ease-in-out infinite; transform-origin: 100% 50%; }
.art .wing-r  { animation: a-flap-r .42s ease-in-out infinite; transform-origin: 0% 50%; }
.art .leg-l   { animation: a-skitter-l .3s ease-in-out infinite; transform-origin: 100% 40%; }
.art .leg-r   { animation: a-skitter-r .3s ease-in-out infinite; transform-origin: 0% 40%; }
.art .mouth   { animation: a-chomp .8s ease-in-out infinite; transform-origin: 50% 0%; }
.art .eyes    { animation: a-blink 3.4s ease-in-out infinite; transform-origin: 50% 50%; }
.art .stem,
.art .antennae { animation: a-wobble 1.6s ease-in-out infinite; transform-origin: 50% 100%; }
.art .bulbs path { animation: a-twinkle 1.4s ease-in-out infinite; }
.art .bulbs path:nth-child(2) { animation-delay: .28s; }
.art .bulbs path:nth-child(3) { animation-delay: .56s; }
.art .bulbs path:nth-child(4) { animation-delay: .84s; }
.art .bulbs path:nth-child(5) { animation-delay: 1.12s; }

/* The ghost's mouth is an "oooo", so it stretches instead of chomping. */
.art[data-motif="ghost"] .mouth { animation: a-ooo 1.5s ease-in-out infinite; }

/*
 * Hold every loop at its resting frame until the card is hovered, focused or
 * pressed. This block has to come after the declarations above: the `animation`
 * shorthand resets animation-play-state to running, so an earlier pause rule
 * would be silently overwritten.
 */
.art [class],
.art .bulbs path { animation-play-state: paused; }

.thing:hover .art [class],
.thing:hover .art .bulbs path,
.thing:focus-within .art [class],
.thing:focus-within .art .bulbs path,
.thing.play .art [class],
.thing.play .art .bulbs path { animation-play-state: running; }

@keyframes a-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-5px); }
}
@keyframes a-squash {
  0%, 100% { transform: scale(1, 1); }
  35%      { transform: scale(1.07, .93); }
  70%      { transform: scale(.96, 1.05); }
}
@keyframes a-rock {
  0%, 100% { transform: rotate(0deg); }
  30%      { transform: rotate(-4deg); }
  70%      { transform: rotate(4deg); }
}
@keyframes a-swish {
  0%, 100% { transform: rotate(0deg); }
  30%      { transform: rotate(-16deg); }
  70%      { transform: rotate(13deg); }
}
@keyframes a-tilt {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(-5deg); }
}
@keyframes a-flap-l {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(-28deg); }
}
@keyframes a-flap-r {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(28deg); }
}
@keyframes a-skitter-l {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(-7deg); }
}
@keyframes a-skitter-r {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(7deg); }
}
@keyframes a-chomp {
  0%, 100% { transform: scaleY(1); }
  50%      { transform: scaleY(.35); }
}
@keyframes a-ooo {
  0%, 100% { transform: scale(1, 1); }
  50%      { transform: scale(1.25, 1.35); }
}
@keyframes a-blink {
  0%, 86%, 100% { transform: scaleY(1); }
  92%           { transform: scaleY(.08); }
}
@keyframes a-wobble {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(7deg); }
}
@keyframes a-twinkle {
  0%, 100% { opacity: 1; }
  50%      { opacity: .3; }
}


/* top menu, in Alexander's colours. Small and quiet on purpose — see menu.js. */
.menu { color: var(--cocoa); }
.menu-btn {
  width: 48px; height: 48px; border-radius: 14px;
  border: 3px solid var(--cocoa); background: transparent;
}
.menu-btn svg { width: 24px; height: 24px; }
.menu-pop {
  background: #FFFFFF; border: 3px solid var(--cocoa); border-radius: 16px;
  box-shadow: 5px 5px 0 var(--grape); min-width: 210px;
}
.menu-pop a { color: var(--cocoa); font-weight: 700; font-size: 1.05rem; padding: .8rem; }
.menu-pop a:hover, .menu-pop a:focus-visible { background: var(--mint); }
