/* Wild Vibes — motion.
   Reveal states, doodle draw-on, ambient forest loops, hover feedback.
   reveal.js adds .is-in / .is-drawn and sets --i and --len.
   Every single thing in here is switched off at the bottom of the file
   for prefers-reduced-motion. */

/* ================================================================== */
/* 1. Reveal on scroll                                                 */
/* ================================================================== */

.reveal {
  opacity: 0;
  transform: translate3d(0, var(--reveal-rise), 0);
  transition:
    opacity var(--dur-4) var(--ease-out),
    transform var(--dur-4) var(--ease-out),
    filter var(--dur-4) var(--ease-out);
  transition-delay: calc(var(--i, 0) * var(--reveal-step));
}
.reveal.is-in {
  opacity: 1;
  transform: none;
  filter: none;
}

/* direction / flavour variants */
.reveal--fade  { transform: none; }
.reveal--up    { transform: translate3d(0, calc(var(--reveal-rise) * 1.8), 0); }
.reveal--left  { transform: translate3d(calc(var(--reveal-rise) * -1.4), 0, 0); }
.reveal--right { transform: translate3d(calc(var(--reveal-rise) * 1.4), 0, 0); }
.reveal--scale { transform: scale(0.955); }
.reveal--soft  { filter: blur(6px); transform: translate3d(0, 12px, 0); }
.reveal--slow  { transition-duration: 1200ms; }

/* --- stagger ------------------------------------------------------ */
/* reveal.js writes --i: 0,1,2… on the direct children of [data-stagger] */

[data-stagger] > .reveal {
  transition-delay: calc(var(--i, 0) * var(--reveal-step));
}

/* A staggering parent does not move itself; its children do. */
.reveal[data-stagger] {
  opacity: 1;
  transform: none;
  transition: none;
}
.reveal[data-stagger] > * {
  opacity: 0;
  transform: translate3d(0, var(--reveal-rise), 0);
  transition:
    opacity var(--dur-4) var(--ease-out),
    transform var(--dur-4) var(--ease-out);
  transition-delay: calc(var(--i, 0) * var(--reveal-step));
}
.reveal[data-stagger].is-in > * {
  opacity: 1;
  transform: none;
}

/* ================================================================== */
/* 2. Doodle draw-on                                                   */
/* ================================================================== */
/* stroke-dasharray / stroke-dashoffset are inherited, so this reaches the
   shadow content of an external <use> too.

   Every stroked path in doodles.svg carries pathLength="100", which
   renormalises its length. That means one dasharray works for every doodle
   with no measuring — and geometry inside an external <use> cannot be
   measured from the page at all, so this is the only way to get it right.
   Inline SVG without pathLength still works: reveal.js measures those and
   writes --len. */

.draw,
.draw :is(path, line, polyline, polygon, circle, ellipse, rect) {
  stroke-dasharray: var(--len, 100);
  stroke-dashoffset: var(--len, 100);
}

.draw.is-drawn,
.draw.is-drawn :is(path, line, polyline, polygon, circle, ellipse, rect) {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset var(--dur-5) var(--ease-in-out);
  transition-delay: calc(var(--i, 0) * 110ms);
}

.draw--fast.is-drawn,
.draw--fast.is-drawn :is(path, line, polyline, polygon, circle, ellipse, rect) {
  transition-duration: 800ms;
}
.draw--slow.is-drawn,
.draw--slow.is-drawn :is(path, line, polyline, polygon, circle, ellipse, rect) {
  transition-duration: 2200ms;
}

/* Solid silhouettes cannot be drawn — fade them instead. */
.draw.doodle--solid,
.draw.doodle--solid :is(path, polygon) {
  stroke-dasharray: none;
  stroke-dashoffset: 0;
}

/* ================================================================== */
/* 3. Ambient forest loops                                             */
/* ================================================================== */

@keyframes wv-float {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
  50%      { transform: translate3d(0, -10px, 0) rotate(1.5deg); }
}

@keyframes wv-sway {
  0%, 100% { transform: rotate(-2.2deg); }
  50%      { transform: rotate(2.2deg); }
}

/* A leaf let go at the top of its box: drifts down and sideways. */
@keyframes wv-drift {
  0%   { opacity: 0; transform: translate3d(0, -18%, 0) rotate(-8deg); }
  10%  { opacity: var(--drift-opacity, 0.5); }
  50%  { transform: translate3d(var(--drift-x, 40px), 46%, 0) rotate(120deg); }
  85%  { opacity: var(--drift-opacity, 0.5); }
  100% { opacity: 0; transform: translate3d(calc(var(--drift-x, 40px) * -0.4), 118%, 0) rotate(310deg); }
}

/* Mist rolling sideways across a section. */
@keyframes wv-mist {
  0%   { opacity: 0;    transform: translate3d(-14%, 0, 0) scaleX(1); }
  22%  { opacity: 0.42; }
  78%  { opacity: 0.42; }
  100% { opacity: 0;    transform: translate3d(16%, -6%, 0) scaleX(1.12); }
}

/* Campfire — irregular on purpose, never a clean sine. */
@keyframes wv-flicker {
  0%   { transform: scale(1) translateY(0);        opacity: 0.9; }
  12%  { transform: scale(1.05) translateY(-1px);  opacity: 1; }
  26%  { transform: scale(0.97) translateY(1px);   opacity: 0.82; }
  41%  { transform: scale(1.07) translateY(-2px);  opacity: 1; }
  55%  { transform: scale(0.99) translateY(0);     opacity: 0.88; }
  68%  { transform: scale(1.04) translateY(-1px);  opacity: 1; }
  83%  { transform: scale(0.96) translateY(1px);   opacity: 0.8; }
  100% { transform: scale(1) translateY(0);        opacity: 0.9; }
}

@keyframes wv-twinkle {
  0%, 100% { opacity: 0.25; transform: scale(0.86); }
  50%      { opacity: 1;    transform: scale(1.08); }
}

@keyframes wv-spin {
  to { transform: rotate(360deg); }
}

/* Birds crossing a section. */
@keyframes wv-fly {
  0%   { opacity: 0; transform: translate3d(-10%, 12px, 0) scale(0.85); }
  15%  { opacity: 0.5; }
  85%  { opacity: 0.5; }
  100% { opacity: 0; transform: translate3d(115%, -34px, 0) scale(1.05); }
}

@keyframes wv-pop {
  from { opacity: 0; transform: scale(0.94); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes wv-fade-up {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}

@keyframes wv-nudge {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(6px); }
}

/* --- loop utility classes ----------------------------------------- */

.anim-float   { animation: wv-float   var(--anim-dur, 7s)  var(--ease-in-out) infinite; }
.anim-sway    { animation: wv-sway    var(--anim-dur, 5.5s) var(--ease-in-out) infinite; transform-origin: 50% 8%; }
.anim-drift   { animation: wv-drift   var(--anim-dur, 15s) linear infinite; }
.anim-mist    { animation: wv-mist    var(--anim-dur, 22s) var(--ease-in-out) infinite; }
.anim-flicker { animation: wv-flicker var(--anim-dur, 2.6s) steps(1, end) infinite; transform-origin: 50% 85%; }
.anim-twinkle { animation: wv-twinkle var(--anim-dur, 3.4s) var(--ease-in-out) infinite; }
.anim-spin    { animation: wv-spin    var(--anim-dur, 46s) linear infinite; transform-origin: 50% 50%; }
.anim-fly     { animation: wv-fly     var(--anim-dur, 26s) linear infinite; }
.anim-nudge   { animation: wv-nudge   var(--anim-dur, 2.2s) var(--ease-in-out) infinite; }

/* stagger a set of looping decorations without touching the markup */
.anim-delay-1 { animation-delay: -2s; }
.anim-delay-2 { animation-delay: -5s; }
.anim-delay-3 { animation-delay: -9s; }
.anim-delay-4 { animation-delay: -14s; }

/* Drifting-leaf field: absolutely positioned inside a .sec.
   Each .leaf-drift wants --drift-x and its own --anim-dur/animation-delay. */
.leaf-field {
  position: absolute;
  inset: 0;
  z-index: var(--z-doodle);
  pointer-events: none;
  overflow: hidden;
}
.leaf-drift {
  position: absolute;
  top: 0;
  width: 1.6rem;
  height: auto;
  color: var(--ctx-doodle);
  fill: none;
  stroke: currentColor;
  opacity: 0;
  animation: wv-drift var(--anim-dur, 16s) linear infinite;
}

/* Campfire — pair a flame element with .anim-flicker inside a .doodle. */
.campfire__flame { transform-origin: 50% 88%; }

/* ================================================================== */
/* 4. Hover feedback                                                   */
/* ================================================================== */

.hover-lift {
  transition: transform var(--dur-2) var(--ease-out),
              box-shadow var(--dur-2) var(--ease-out);
}
.hover-lift:hover { transform: translateY(-4px); box-shadow: var(--sh-3); }

.hover-grow { transition: transform var(--dur-2) var(--ease-spring); }
.hover-grow:hover { transform: scale(1.03); }

.hover-tilt { transition: transform var(--dur-3) var(--ease-spring); }
.hover-tilt:hover { transform: rotate(-1.2deg) translateY(-3px); }

/* Media zoom for any framed photo that is not inside a .card */
.media-frame img { transition: transform 900ms var(--ease-out); }
.media-frame:hover img,
a:hover > .media-frame img { transform: scale(1.04); }

/* ================================================================== */
/* 5. Header condense                                                  */
/* ================================================================== */

.site-head { will-change: box-shadow; }
.site-head__in,
.brand__mark,
.brand__tag { will-change: auto; }

/* First paint of the drawer contents, once open. */
.site-head.is-open .nav__list > li {
  animation: wv-fade-up var(--dur-3) var(--ease-out) both;
  animation-delay: calc(60ms + var(--i, 0) * 38ms);
}
.site-head.is-open .nav__list > li:nth-child(1) { --i: 0; }
.site-head.is-open .nav__list > li:nth-child(2) { --i: 1; }
.site-head.is-open .nav__list > li:nth-child(3) { --i: 2; }
.site-head.is-open .nav__list > li:nth-child(4) { --i: 3; }
.site-head.is-open .nav__list > li:nth-child(5) { --i: 4; }
.site-head.is-open .nav__list > li:nth-child(6) { --i: 5; }
.site-head.is-open .nav__list > li:nth-child(7) { --i: 6; }
.site-head.is-open .nav__list > li:nth-child(8) { --i: 7; }

/* ================================================================== */
/* 6. Lightbox                                                         */
/* ================================================================== */

.lightbox.is-open .lightbox__img,
.lightbox[open] .lightbox__img {
  animation: wv-pop var(--dur-3) var(--ease-spring) both;
}
.lightbox.is-open .lightbox__bar,
.lightbox[open] .lightbox__bar,
.lightbox.is-open .lightbox__cap,
.lightbox[open] .lightbox__cap {
  animation: wv-fade-up var(--dur-3) var(--ease-out) both;
  animation-delay: 90ms;
}

/* ================================================================== */
/* 7. Scroll cue                                                       */
/* ================================================================== */

.scroll-cue {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45rem;
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-kicker);
  text-transform: uppercase;
  color: var(--ctx-muted);
  text-decoration: none;
}
.scroll-cue svg {
  width: 1.5rem;
  height: 1.5rem;
  fill: none;
  stroke: currentColor;
  animation: wv-nudge 2.2s var(--ease-in-out) infinite;
}

/* ================================================================== */
/* 8. Reduced motion — kill everything                                 */
/* ================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0s !important;
    transition-duration: .001ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
  .reveal,
  .reveal[data-stagger] > *,
  [data-stagger] > .reveal {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }
  .draw,
  .draw :is(path, line, polyline, polygon, circle, ellipse, rect) {
    stroke-dasharray: none !important;
    stroke-dashoffset: 0 !important;
  }
  .leaf-field, .leaf-drift { display: none !important; }
  .anim-float, .anim-sway, .anim-drift, .anim-mist, .anim-flicker,
  .anim-twinkle, .anim-spin, .anim-fly, .anim-nudge, .scroll-cue svg {
    animation: none !important;
  }
  .hover-lift:hover, .hover-grow:hover, .hover-tilt:hover,
  .card:hover, .btn:hover, .gallery-item:hover, .rule-card:hover {
    transform: none !important;
  }
  .card:hover .card__media img,
  .gallery-item:hover img,
  .media-frame:hover img { transform: none !important; }
}

/* Horizontal reveal offsets push an element outside the viewport on a narrow
   screen, where the wrap padding is too small to absorb them — a few px of
   phantom overflow before the element animates in, and a permanently offset
   photo if the observer never fires. Below the two-column breakpoint there is
   no sideways motion to suggest anyway, so rise instead. */
@media (max-width: 899px) {
  .reveal--left,
  .reveal--right { transform: translate3d(0, var(--reveal-rise), 0); }
}
