/* ==========================================================================
   IX · FOOTER — how the page hands over to its close.

     body[data-rbs-footer="flow"]    the shipped ending: the footer scrolls in
     body[data-rbs-footer="reveal"]  curtain lift: the footer waits beneath
                                     the page and the last section lifts off it

   REVEAL MECHANICS — no position:fixed, no document-flow change, Lenis-safe.
   The curtain wrapper (sections/footer.html ships it) reaches 100vh UP under
   the closing CTA via a negative top margin and clips that lead region away
   with clip-path, so its net flow height stays exactly the footer's height —
   zero CLS on toggle, document length untouched. Inside, the footer is
   `position: sticky; bottom: 0` with 100vh of travel from a ::before strut:
   through the last stretch of scroll it holds still at the viewport bottom
   behind the clip edge, and the page lifts off it like a curtain. Pure CSS
   once armed — no per-frame JS in the structural path.

   js/areas/footer.js arms this with data-rbs-fit="pin" only when the footer
   actually fits the viewport (ResizeObserver-checked) and motion is authored.
   A footer taller than the viewport gets data-rbs-fit="tall" instead: plain
   flow, depth pass only, capped to one viewport of travel. No attribute
   (JS dead, or motion ≠ authored) = the shipped in-flow footer, always
   correct — nothing is ever hidden waiting for a reveal.

   The depth pass is one custom property: the area JS writes --rbs-footer-p
   (0 = still under the page → 1 = revealed) on the wrapper each scroll frame;
   CSS maps it to a content settle (translateY −depth → 0), a brighten
   (dim → 1) and the page edge's cast shadow fading out. p defaults to 1, so
   a dead pipeline can never strand a dimmed footer. Scroll-linked values must
   track the finger 1:1 — deliberately no transition anywhere in that path.
   ========================================================================== */

/* --------------------------------------------------------------------------
   CURTAIN — structural pin. Guarded by @supports as a unit: without inset()
   the footer would pin visibly over the closing CTA, so it is all or nothing.
   -------------------------------------------------------------------------- */
body[data-rbs-footer="reveal"] .rb-footer-curtain[data-rbs-fit] { position: relative; }

@supports (clip-path: inset(0 0 0 0)) {
  body[data-rbs-motion-level="authored"][data-rbs-footer="reveal"]
    .rb-footer-curtain[data-rbs-fit="pin"] {
    /* The lead: how far the wrapper reaches up under the page. Any constant
       ≥ the footer's height works; 100vh always is, because 'pin' is only
       granted when the footer fits the viewport. Must stay identical across
       margin, strut and clip — hence the one property. */
    --_ftr-lead: 100vh;

    display: flex;
    flex-direction: column;
    margin-top: calc(-1 * var(--_ftr-lead));
    clip-path: inset(var(--_ftr-lead) 0 0 0);
  }

  /* The strut gives the sticky footer its travel room. */
  body[data-rbs-motion-level="authored"][data-rbs-footer="reveal"]
    .rb-footer-curtain[data-rbs-fit="pin"]::before {
    content: "";
    flex: none;
    height: var(--_ftr-lead);
  }

  /* Pinned to the viewport bottom while the containing block scrolls;
     settles into its exact flow slot at document end. Sticky never leaves
     its containing block, so the clip edge is the only reveal edge. */
  body[data-rbs-motion-level="authored"][data-rbs-footer="reveal"]
    .rb-footer-curtain[data-rbs-fit="pin"] > .rb-footer {
    position: sticky;
    bottom: 0;
  }
}

/* Tall fallback: no pin, but the depth pass may translate content up to
   64px — `clip` keeps it from ever poking above the wrapper into the CTA. */
body[data-rbs-footer="reveal"] .rb-footer-curtain[data-rbs-fit="tall"] { overflow: clip; }

/* --------------------------------------------------------------------------
   DEPTH — the settle. Content starts −depth above its seat at 0.85 opacity
   and eases home as the curtain lifts. Number × length keeps the whole map
   in calc(); no transitions — p IS the timeline.
   -------------------------------------------------------------------------- */
body[data-rbs-motion-level="authored"][data-rbs-footer="reveal"]
  .rb-footer-curtain[data-rbs-fit] .rb-footer > .rb-container {
  transform: translateY(calc((var(--rbs-footer-p, 1) - 1) * var(--rbs-footer-depth, 24px)));
  opacity: calc(var(--rbs-footer-dim, 0.85)
                + ((1 - var(--rbs-footer-dim, 0.85)) * var(--rbs-footer-p, 1)));
  will-change: transform, opacity;
}

/* --------------------------------------------------------------------------
   EDGE SHADOW — the page bottom casts onto the surfacing footer, and the
   shadow burns off as the reveal completes. Sits at the reveal edge: the
   clip line in pin mode (--_ftr-lead), the wrapper top in tall mode (0px
   fallback). The toggle knob arrives as --rbs-footer-shadow: 1|0 and simply
   multiplies the opacity.
   -------------------------------------------------------------------------- */
body[data-rbs-motion-level="authored"][data-rbs-footer="reveal"]
  .rb-footer-curtain[data-rbs-fit]::after {
  content: "";
  position: absolute;
  top: var(--_ftr-lead, 0px);
  inset-inline: 0;
  height: var(--rb-ref-space-8);   /* 40 */
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--rb-ref-black) 50%, transparent),
    transparent
  );
  opacity: calc((1 - var(--rbs-footer-p, 1)) * var(--rbs-footer-shadow, 1));
}

/* --------------------------------------------------------------------------
   FOOTER MICRO — the social dots. Pure feedback: every motion level, fine
   pointers only. 220ms swift lift + brand tint; the link hover treatment
   stays the links area's business.
   -------------------------------------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  .rb-footer__social-dot {
    transition:
      transform var(--rb-sys-duration-2) var(--rb-sys-ease-swift),
      background-color var(--rb-sys-duration-2) var(--rb-sys-ease-swift);
  }

  .rb-footer__social-dot:hover {
    transform: translateY(-2px);
    background: var(--rb-ref-teal-600);
  }

  /* Reduced motion: keep the color, drop the travel. */
  body[data-rbs-motion-level="essential"] .rb-footer__social-dot:hover { transform: none; }
}
