/* Playful layer (experiment, 5 Nov 2026). Generated by tools/playful-css.mjs.
   To revert: remove the playful.css and playful.js tags from the pages. */

:root { --wave-a: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201440%2030'%20preserveAspectRatio%3D'none'%3E%3Cpath%20d%3D'M0%2030%20L0%2011.0%20C66.6%204.5%20123.6%207.3%20190.2%2013.8%20C244.1%2019.1%20290.4%2024.1%20344.3%2018.7%20C409.7%2012.9%20465.7%209.8%20531.1%2015.7%20C598.3%2023.6%20655.9%2023.2%20723.1%2015.3%20C784.5%207.9%20837.1%205.6%20898.5%2013.0%20C973.5%2020.2%201037.7%2019.5%201112.7%2012.3%20C1177.2%205.4%201232.4%209.4%201296.9%2016.3%20C1347.0%2022.2%201389.9%2016.9%201440.0%2011.0%20L1440%2030%20Z'%20fill%3D'black'%2F%3E%3C%2Fsvg%3E"); --wave-b: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201440%2030'%20preserveAspectRatio%3D'none'%3E%3Cpath%20d%3D'M0%2030%20L0%2011.0%20C78.2%204.1%20145.2%2012.4%20223.3%2019.2%20C285.3%2025.1%20338.4%2020.9%20400.4%2015.1%20C463.9%209.6%20518.4%208.8%20581.9%2014.3%20C656.0%2023.0%20719.6%2026.1%20793.7%2017.3%20C849.6%2011.9%20897.4%206.7%20953.3%2012.1%20C1007.7%2020.8%201054.4%2020.5%201108.9%2011.9%20C1161.5%206.6%201206.6%2010.6%201259.2%2016.0%20C1322.5%2024.9%201376.7%2019.9%201440.0%2011.0%20L1440%2030%20Z'%20fill%3D'black'%2F%3E%3C%2Fsvg%3E"); --wave-h: 30px; }

/* ---- Wavy, hand-drawn top edges on every section after the first.
   A strip of the section's own colour and paper texture rises 30px into the
   section above, cut to a wave. Content is never clipped by it. */
.band { overflow-x: clip; overflow-y: visible; }
.band + .band:not(.hero + .band), .site-footer { position: relative; }
.band + .band:not(.hero + .band)::before, .site-footer::before {
  content: ""; position: absolute; left: 0; right: 0; top: calc(-1 * var(--wave-h) + 1px); height: var(--wave-h);
  background: inherit; background-blend-mode: inherit; background-position: 0 calc(-1 * var(--wave-h));
  -webkit-mask: var(--wave-a) 0 0 / 1440px 100% repeat-x; mask: var(--wave-a) 0 0 / 1440px 100% repeat-x;
  pointer-events: none; z-index: 3;
}
.band + .band:nth-of-type(even)::before { -webkit-mask-image: var(--wave-b); mask-image: var(--wave-b); }
.site-footer { overflow: visible; }
.site-footer::before { background: var(--blue-night); }
/* the blue section's glow is placed in pixels, so the strip can continue it exactly */
.band--blue::before { background: radial-gradient(1000px 700px at 70% calc(300px + var(--wave-h)), #2C74C0 0%, #1E5FA8 50%, #174D8D 100%) !important; }

/* A Tim peeking over the top edge of the Not Enough Noras section. */
.peek-tim { position: absolute; z-index: 4; right: 9%; top: -62px; width: 92px; height: auto; transform: rotate(14deg); pointer-events: none;
  filter: drop-shadow(0 6px 8px rgba(22, 40, 74, 0.25)); }
@media (max-width: 860px) { .peek-tim { width: 70px; top: -48px; right: auto; left: 6%; transform: rotate(-12deg) scaleX(-1); } }

/* ---- Book covers: a quick wiggle on hover (mouse only). */
@keyframes wiggle { 0% { rotate: 0deg; } 18% { rotate: -3deg; } 40% { rotate: 2.4deg; } 60% { rotate: -1.4deg; } 80% { rotate: 0.6deg; } 100% { rotate: 0deg; } }
@media (hover: hover) and (pointer: fine) {
  /* playful.js adds .is-wiggling on hover and removes it when the wobble finishes,
     so it always plays to the end instead of cutting off when the mouse leaves */
  .is-wiggling { animation: wiggle 640ms ease-in-out; }
  .tile { transition: transform 200ms var(--ease-out); }
  .tile:hover { transform: translateY(-4px) rotate(-0.6deg); }
}

/* ---- Speech bubbles pop in as they scroll into view (only when JS is on). */
.js-pop .say { opacity: 0; transform: translateY(14px) scale(0.94) rotate(var(--tilt, 0deg)); transition: opacity 420ms var(--ease-out), transform 520ms var(--ease-back); }
.js-pop .say.is-in { opacity: 1; transform: translateY(0) scale(1) rotate(var(--tilt, 0deg)); }
.says .say:nth-child(3n+1) { --tilt: -1.6deg; }
.says .say:nth-child(3n+2) { --tilt: 1.2deg; }
.says .say:nth-child(3n) { --tilt: -0.6deg; }
.say--big { --tilt: -0.8deg; }

/* ---- The little Tims on the bubbles bob gently. */
@keyframes bob { from { translate: 0 0; } to { translate: 0 -6px; } }
.praise__tim { animation: bob 2.4s ease-in-out infinite alternate; }
.praise__tim--b { animation-delay: -0.8s; } .praise__tim--c { animation-delay: -1.6s; }

@media (prefers-reduced-motion: reduce) {
  .js-pop .say { opacity: 1; transform: rotate(var(--tilt, 0deg)); transition: none; }
  .praise__tim { animation: none; }
  .is-wiggling { animation: none; }
  .tile, .tile:hover { transition: none; transform: none; }
}
