/* ========== DRAG TO SCROLL ========== */
/* Additive only - lets mousedown+drag scroll the page vertically like
   Figma/Google Maps, on top of normal wheel/trackpad scroll (untouched).
   Logic lives in js/drag-scroll.js. */
body {
  cursor: grab;
}

body.is-dragging {
  cursor: grabbing;
}

/* Keep interactive elements showing their usual pointer affordance instead
   of inheriting body's grab cursor. */
.nav a,
.socials a,
.rc-logo-link,
.logo-link {
  cursor: pointer;
}

/* ========== SCROLL REVEAL (logic lives in js/idle-reveal.js and
   js/scroll-reveal.js) ========== */
/* Pure-CSS initial state, applied immediately at paint - not set via JS,
   so there's no flash-of-visible-content while GSAP/ScrollTrigger are
   still loading from CDN. 50px matches config.js's reveal.distance.
   Covers all six scroll-scrubbed blocks: hero copy, big title, the three
   "— 00X" columns, and the footer. */
.reveal {
  opacity: 0;
  transform: translateY(50px);
}

/* Both hero blocks manage their own `y` offset via JS (js/hero-entrance.js
   for .desc, js/title-wave.js for .title-block) instead of the shared
   translateY(50px) above, so this cancels that shared value rather than
   letting it double up with JS's own identical starting offset. .desc's
   opacity is also driven by that same scrub; .title-block's opacity is
   fixed at 1 always (see js/title-wave.js) - only its per-letter masks
   and its own `y` ever animate for that block. */
.title-block.reveal,
.desc.reveal {
  transform: none;
}

/* Accessibility safety net independent of JS: guarantees content is fully
   visible for reduced-motion users even if script.js fails to load at all,
   not just when its own matchMedia check runs. */
@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
  }
}
