/* ============================================================================
   KABEELA MOTION LAYER  ·  kabeela-motion.css
   A reusable scroll + entry animation vocabulary for kabeela.community.
   Motion is geological/botanical: things settle, grow, and resolve.
   Animates only transform + opacity (one exception: clip-path for images).

   HOW IT WORKS
   - An inline <head> script adds `.js` to <html>. All hidden start-states are
     scoped to `.js` so that with no JS (or slow JS) content shows instantly.
   - kabeela-motion.js runs ONE IntersectionObserver, adds `.kb-in` when an
     element enters view, then unobserves it (reveals never re-trigger).
   - Everything is driven by data- attributes so you apply it in markup only.

   EASING: one curve site-wide.
   TO DELETE AN EFFECT: remove its commented block below + stop using its attr.
   ========================================================================== */

:root{
  --kb-ease: cubic-bezier(0.16, 1, 0.3, 1);
  --kb-veil: #F4F0E8;            /* limestone veil for page transitions */
}

/* Base hidden state — ONLY when JS is present. No JS = content visible. */
.js [data-reveal],
.js [data-reveal-group] > *,
.js [data-quote] .kb-word{
  opacity: 0;
}

/* ----------------------------------------------------------------------------
   EFFECT 1 · HERO ENTRY  (runs at load, not on scroll)
   Background image resolves from 12px blur to 0 over 900ms, immediately.
   Headline lines fade up 24px over 700ms, staggered 120ms. Land focuses first.
   -------------------------------------------------------------------------- */
[data-hero-img]{
  animation: kb-hero-focus 900ms var(--kb-ease) both;
}
@keyframes kb-hero-focus{
  from{ filter: blur(12px); }
  to  { filter: blur(0); }
}
.js [data-hero-line]{
  opacity: 0;
  transform: translateY(24px);
  animation: kb-line 700ms var(--kb-ease) forwards;
  /* Hold the words back so the land focuses and is seen on its own first,
     then they settle onto it. Tune the beat with --kb-hero-delay. */
  animation-delay: calc(var(--kb-i, 0) * 120ms + var(--kb-hero-delay, 2400ms));
}
@keyframes kb-line{ to{ opacity: 1; transform: none; } }

/* Hero scrim — the dark overlay starts nearly clear so the land reads brightly
   on its own, then deepens back to its resting value as the words arrive
   (keeps text legible). Put [data-hero-scrim] on the hero's gradient overlay. */
.js [data-hero-scrim]{
  animation: kb-hero-scrim 1000ms var(--kb-ease) both;
  animation-delay: calc(var(--kb-hero-delay, 2400ms) - 900ms);
}
@keyframes kb-hero-scrim{ from{ opacity: .22; } to{ opacity: 1; } }

/* ----------------------------------------------------------------------------
   EFFECT 2 · AMBIENT HERO BREATH  (hero image only)
   Scales 1 -> 1.04 over 20s. No reset, no loop. Sits on a wrapper so it never
   fights the blur (filter) or any parallax transform on the image itself.
   -------------------------------------------------------------------------- */
[data-hero-breath]{
  animation: kb-breath 20s var(--kb-ease) forwards;
}
@keyframes kb-breath{ from{ transform: scale(1); } to{ transform: scale(1.04); } }

/* ----------------------------------------------------------------------------
   EFFECT 3 · TERRACE CASCADE
   [data-reveal-group] children reveal as a stepped diagonal: each row 90ms
   later and 12px further right than the last — content stacks like terraces.
   (kabeela-motion.js sets --kb-i = child index.)
   -------------------------------------------------------------------------- */
.js [data-reveal-group] > *{
  transform: translate(calc(var(--kb-i, 0) * 12px), 20px);
  transition: opacity 700ms var(--kb-ease), transform 700ms var(--kb-ease);
  transition-delay: calc(var(--kb-i, 0) * 90ms);
}
[data-reveal-group].kb-in > *{ opacity: 1; transform: none; }

/* ----------------------------------------------------------------------------
   EFFECT 4 · GROWTH REVEAL  (lists + cards)
   transform-origin bottom; scaleY 0.96 -> 1 plus opacity, 600ms.
   Elements grow up from their base rather than flying in.
   -------------------------------------------------------------------------- */
.js [data-reveal="growth"]{
  transform-origin: bottom center;
  transform: scaleY(0.96);
  transition: opacity 600ms var(--kb-ease), transform 600ms var(--kb-ease);
}
[data-reveal="growth"].kb-in{ opacity: 1; transform: none; }

/* ----------------------------------------------------------------------------
   EFFECT 5 · DIVIDER DRAW  (1px rules between sections)
   scaleY 0 -> 1 from the top edge, 800ms. Give the element height + a bg.
   -------------------------------------------------------------------------- */
.js [data-reveal="divider"]{
  transform-origin: top center;
  transform: scaleY(0);
  transition: transform 800ms var(--kb-ease);
  opacity: 1;                 /* draw, don't fade */
}
[data-reveal="divider"].kb-in{ transform: scaleY(1); }

/* ----------------------------------------------------------------------------
   EFFECT 6 · IMAGE MASK REVEAL  (all non-hero photography)
   clip-path inset wipe from the bottom edge upward, 900ms.
   Layer released on transitionend by kabeela-motion.js.
   -------------------------------------------------------------------------- */
.js [data-reveal="mask"]{
  clip-path: inset(0 0 100% 0);
  transition: clip-path 900ms var(--kb-ease), opacity 900ms var(--kb-ease);
}
[data-reveal="mask"].kb-in{ clip-path: inset(0 0 0 0); opacity: 1; }

/* ----------------------------------------------------------------------------
   EFFECT 7 · PULL-QUOTE WORD STAGGER  (strictly one per page — see README)
   Words fade up 40ms apart. kabeela-motion.js wraps words in .kb-word.
   -------------------------------------------------------------------------- */
.js [data-quote] .kb-word{
  display: inline-block;
  transform: translateY(0.4em);
  transition: opacity 500ms var(--kb-ease), transform 500ms var(--kb-ease);
}
[data-quote].kb-in .kb-word{ opacity: 1; transform: none; }

/* ----------------------------------------------------------------------------
   EFFECT 8 · LAND-STAT COUNTERS
   Count up over 1.2s ease-out on entering view (kabeela-motion.js).
   Reserve final width so nothing shifts while counting (tabular-nums + attr).
   -------------------------------------------------------------------------- */
[data-count]{ font-variant-numeric: tabular-nums; }

/* ----------------------------------------------------------------------------
   EFFECT 9 · CARD HOVER
   2% scale + a softening shadow over 400ms. No lift, no rotation.
   -------------------------------------------------------------------------- */
[data-card]{ transition: transform 400ms var(--kb-ease), box-shadow 400ms var(--kb-ease); }
@media (hover: hover){
  [data-card]:hover{ transform: scale(1.02); box-shadow: 0 10px 34px rgba(28,22,14,0.14); }
}

/* ----------------------------------------------------------------------------
   EFFECT 10 · NAV OPEN
   Items fade in 60ms apart while the backdrop blurs in.
   Toggle `.kb-nav-open` on the menu container; give items [data-nav-item].
   -------------------------------------------------------------------------- */
[data-nav-backdrop]{ transition: opacity 300ms var(--kb-ease), backdrop-filter 300ms var(--kb-ease); }
.js [data-nav-item]{ opacity: 0; transform: translateY(8px); transition: opacity 300ms var(--kb-ease), transform 300ms var(--kb-ease); }
.kb-nav-open [data-nav-item]{ opacity: 1; transform: none; transition-delay: calc(var(--kb-i, 0) * 60ms); }

/* ----------------------------------------------------------------------------
   EFFECT 11 · PAGE TRANSITIONS  (cross-document View Transitions API)
   Support today: Chromium 126+. Everywhere else this is silently ignored and
   navigation is instant (degrades to no transition) — nothing to detect in JS.
   Default: a 350ms cross-fade so the six pages feel like one continuous place.
   To upgrade this to the full limestone-veil wipe, see the README (needs a
   veil element per page); the keyframes are provided there.
   -------------------------------------------------------------------------- */
@view-transition{ navigation: auto; }
::view-transition-old(root),
::view-transition-new(root){ animation-duration: 350ms; animation-timing-function: var(--kb-ease); }
@media (prefers-reduced-motion: reduce){ @view-transition{ navigation: none; } }

/* ----------------------------------------------------------------------------
   REDUCED MOTION · opacity only. No transform, parallax, counters, or veils.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce){
  .js [data-reveal],
  .js [data-reveal-group] > *,
  .js [data-hero-line],
  .js [data-quote] .kb-word{
    transform: none !important;
    transition: opacity 400ms ease !important;
  }
  [data-hero-img]{ animation: none !important; filter: none !important; }
  [data-hero-breath]{ animation: none !important; }
  .js [data-hero-scrim]{ animation: none !important; }
  .js [data-reveal="divider"]{ transform: none !important; }
  .js [data-reveal="mask"]{ clip-path: none !important; }
  [data-card]:hover{ transform: none !important; }
}
