/* Motion (assets/js/motion.js). Every rule hangs off html.motion, which the
   script adds only when the visitor has not asked for reduced motion, so a
   page without JS is never left with hidden content. Colours from tokens. */

/* --- slide-ins ------------------------------------------------------------ */
/* Pieces waiting off to the side must not widen the page. */
.motion body { overflow-x: clip; }
.motion [data-reveal] {
  opacity: 0;
  transition: opacity 700ms cubic-bezier(0.2, 0.7, 0.2, 1), transform 800ms cubic-bezier(0.2, 0.7, 0.2, 1);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
.motion [data-reveal="up"]    { transform: translate3d(0, 48px, 0); }
.motion [data-reveal="left"]  { transform: translate3d(-80px, 0, 0); }
.motion [data-reveal="right"] { transform: translate3d(80px, 0, 0); }
.motion [data-reveal="pop"]   { transform: translate3d(0, 24px, 0) scale(0.85); }
.motion [data-reveal="fade"]  { transform: none; }
/* the logo wall's four quadrants (motion.js logoWall()) */
.motion [data-reveal="logo-ul"] { transform: translate3d(-90px, 0, 0); }
.motion [data-reveal="logo-ur"] { transform: translate3d(90px, 0, 0); }
.motion [data-reveal="logo-ll"] { transform: translate3d(-70px, 70px, 0); }
.motion [data-reveal="logo-lr"] { transform: translate3d(70px, 70px, 0); }
.motion [data-reveal].is-in   { opacity: 1; transform: none; }

/* --- home hero, on load: the name slides in from the left as it fades up,
   the button fades in just after. ---------------------------------------- */
.motion .hero__title { animation: hero-title 1100ms cubic-bezier(0.2, 0.7, 0.2, 1) both; }
.motion .hero__body .hero__actions { animation: hero-fade 900ms ease 500ms both; }
@keyframes hero-title { from { opacity: 0; transform: translate3d(-120px, 0, 0); } }
@keyframes hero-fade { from { opacity: 0; } }

/* --- parallax ------------------------------------------------------------- */
/* Hero photos drift down with the scroll (motion.js doubles every speed);
   scaled up so the drift never shows an edge. */
.motion .hero__media img,
.motion .page-hero__media img {
  transform: translate3d(0, calc(var(--parallax, 0px) * -1), 0) scale(1.25);
  will-change: transform;
}

/* --- floaters: big line-art records, mics and headphones that drift in from
   a side and hang half off the edge of a band (topnotch_floater()). ------- */
.floater {
  position: absolute; z-index: 0; pointer-events: none;
  width: clamp(160px, 22vw, 340px); aspect-ratio: 1;
  color: var(--floater, currentColor); opacity: 0.16;
}
.floater svg { width: 100%; height: 100%; display: block; fill: none; stroke: currentColor; stroke-width: 1.5; }
.floater--left  { left: clamp(-120px, -6vw, -40px); }
.floater--right { right: clamp(-120px, -6vw, -40px); }
.floater--top    { top: 8%; }
.floater--bottom { bottom: 18%; }
.floater__spin { transform-origin: 50% 50%; animation: floater-spin 14s linear infinite; }
@keyframes floater-spin { to { transform: rotate(360deg); } }
.motion .floater { transform: translate3d(0, var(--parallax, 0px), 0); transition: none; }
.motion .floater[data-reveal] { opacity: 0; }
.motion .floater[data-reveal].is-in { opacity: 0.16; transition: opacity 1200ms ease; }
.motion .floater--left[data-reveal]:not(.is-in)  { translate: -140px 0; }
.motion .floater--right[data-reveal]:not(.is-in) { translate: 140px 0; }
.motion .floater[data-reveal] { transition: opacity 1200ms ease, translate 1400ms cubic-bezier(0.2, 0.7, 0.2, 1); }
/* a band with a floater clips it at the sides only (the separator pokes 2px
   out the bottom) */
.section:has(> .floater) { position: relative; overflow-x: clip; }
.page-hero .floater { --floater: var(--on-night); opacity: 0.1; }
.motion .page-hero .floater[data-reveal].is-in { opacity: 0.1; }
/* content stays above the floaters */
.band > .wrap, .section > .wrap, .hero__body, .page-hero__body { position: relative; z-index: 1; }

/* --- cursor: a spinning record; a microphone over anything clickable ----- */
.has-cursor, .has-cursor * { cursor: none !important; }
.has-cursor input:not([type="button"]):not([type="submit"]):not([type="checkbox"]):not([type="radio"]),
.has-cursor textarea, .has-cursor [contenteditable] { cursor: text !important; }
.cursor {
  position: fixed; top: 0; left: 0; z-index: 2147483000; pointer-events: none;
  width: 0; height: 0; opacity: 0; transition: opacity 150ms;
}
.cursor.is-on { opacity: 1; }
.cursor.is-hidden { opacity: 0; }
.cursor svg { position: absolute; width: 30px; height: 30px; max-width: none; transition: opacity 120ms, transform 160ms cubic-bezier(0.3, 1.6, 0.5, 1); }
.cursor__record { left: -15px; top: -15px; animation: cursor-spin 1.8s linear infinite; }
.cursor__vinyl { fill: #111; stroke: rgb(255 255 255 / 0.5); stroke-width: 1; }
.cursor__groove { fill: none; stroke: rgb(255 255 255 / 0.22); stroke-width: 0.8; }
.cursor__shine { fill: none; stroke: rgb(255 255 255 / 0.55); stroke-width: 1.4; stroke-linecap: round; }
.cursor__label { fill: var(--accent); }
.cursor__hole { fill: #111; }
.cursor__mic { left: -15px; top: -2px; opacity: 0; transform: scale(0.4) rotate(-20deg); }
.cursor__mic-head { fill: #111; stroke: rgb(255 255 255 / 0.6); stroke-width: 1.2; }
.cursor__mic-grille { stroke: var(--accent); stroke-width: 1.4; stroke-linecap: round; }
.cursor__mic-stand { fill: none; stroke: #111; stroke-width: 2.6; stroke-linecap: round; }
.cursor.is-mic .cursor__record { opacity: 0; transform: scale(0.4); }
.cursor.is-mic .cursor__mic { opacity: 1; transform: rotate(-18deg); }
.cursor.is-scratch .cursor__record { animation: cursor-scratch 320ms ease-out, cursor-spin 1.8s linear 320ms infinite; }
@keyframes cursor-spin { to { transform: rotate(360deg); } }
@keyframes cursor-scratch { 0% { transform: rotate(0); } 40% { transform: rotate(-70deg); } 100% { transform: rotate(40deg); } }
