/* ==========================================================================
   IX · REVEAL — the entrance system for every text block on the page.

   Contract with js/areas/reveal.js:
   · JS decorates targets with [data-rbs-rv] and a hierarchy index
     --rbs-reveal-i; the ACTIVE variant lives on <body data-rbs-reveal="…">.
   · Hiding exists ONLY while JS holds `.is-rbs-armed` on a section — there
     is no static hidden state, so a JS failure can never blank content.
   · `.is-rbs-playing` carries the transition; JS removes it once the
     choreography resolves, so these transitions never tax later state
     changes (hover, accordion, carousel) on the same elements.
   · Armed states have NO transition — arming and re-arming are instant and
     happen offscreen; the enter transition retargets safely mid-flight.

   Knobs (Studio writes these on :root):
     --rbs-reveal-stagger   sibling + line delay        default 60ms
     --rbs-reveal-dist      rise travel                 default 20px
     --rbs-reveal-dur       base duration (editorial,   default 700ms
                            so it multiplies by --rbs-motion-scale)
   ========================================================================== */

/* --- line masks (variant: lines) ------------------------------------------
   Built at runtime around each visual heading line. clip-path is the reveal
   primitive; the negative block insets give ascenders/descenders room at
   rest — the page's display leading is 0.92, tighter than the glyph box. */
.rbs-line {
  display: block;
  clip-path: inset(-0.2em -0.15em);
}
.rbs-line__inner { display: block; }

/* ==========================================================================
   ARMED — hidden, instantly (no transition), only under an active variant
   ========================================================================== */

body[data-rbs-reveal="rise"]  .is-rbs-armed [data-rbs-rv],
body[data-rbs-reveal="lines"] .is-rbs-armed [data-rbs-rv]:not([data-rbs-rv-split]) {
  opacity: 0;
  transform: translateY(var(--rbs-reveal-dist, 20px));
}

body[data-rbs-reveal="focus"] .is-rbs-armed [data-rbs-rv] {
  opacity: 0;
  transform: translateY(calc(var(--rbs-reveal-dist, 20px) * 0.6));
  filter: blur(var(--rbs-reveal-blur, 12px));   /* capped at 12px — Safari cost */
}

/* split headings stay opaque; their lines hide inside their own clips */
body[data-rbs-reveal="lines"] .is-rbs-armed [data-rbs-rv-split] .rbs-line__inner {
  transform: translateY(calc(100% + 0.3em));
}

/* ==========================================================================
   PLAYING — transition to rest, hierarchy stagger via --rbs-reveal-i
   ========================================================================== */

/* Tabs' own panel choreography (.is-rbs-exit/-enter) must own `transition`
   on the tab panels while it runs — the reveal cedes the property there. */
body[data-rbs-reveal="rise"]  .is-rbs-playing [data-rbs-rv]:not(.is-rbs-exit):not(.is-rbs-enter):not(.is-rbs-enter-go),
body[data-rbs-reveal="lines"] .is-rbs-playing [data-rbs-rv]:not([data-rbs-rv-split]):not(.is-rbs-exit):not(.is-rbs-enter):not(.is-rbs-enter-go) {
  transition:
    opacity   calc(var(--rbs-reveal-dur, 700ms) * var(--rbs-motion-scale, 1))
              var(--rbs-ease-reveal, var(--rb-sys-ease-expo)),
    transform calc(var(--rbs-reveal-dur, 700ms) * var(--rbs-motion-scale, 1))
              var(--rbs-ease-reveal, var(--rb-sys-ease-expo));
  transition-delay: calc(var(--rbs-reveal-i, 0) * var(--rbs-reveal-stagger, 60ms));
}

/* focus: the blur racks sharp a beat ahead of the settle — lens first */
body[data-rbs-reveal="focus"] .is-rbs-playing [data-rbs-rv]:not(.is-rbs-exit):not(.is-rbs-enter):not(.is-rbs-enter-go) {
  transition:
    opacity   calc(var(--rbs-reveal-dur, 700ms) * var(--rbs-motion-scale, 1))
              var(--rbs-ease-reveal, var(--rb-sys-ease-expo)),
    transform calc(var(--rbs-reveal-dur, 700ms) * var(--rbs-motion-scale, 1))
              var(--rbs-ease-reveal, var(--rb-sys-ease-expo)),
    filter    calc(var(--rbs-reveal-dur, 700ms) * 0.85 * var(--rbs-motion-scale, 1))
              var(--rbs-ease-reveal, var(--rb-sys-ease-expo));
  transition-delay: calc(var(--rbs-reveal-i, 0) * var(--rbs-reveal-stagger, 60ms));
}

/* lines: each line rides the block delay plus its own line index; a touch
   longer than the block reveals (700→~800ms) so the masks feel unhurried */
body[data-rbs-reveal="lines"] .is-rbs-playing [data-rbs-rv-split] .rbs-line__inner {
  transition:
    transform calc(var(--rbs-reveal-dur, 700ms) * 1.15 * var(--rbs-motion-scale, 1))
              var(--rbs-ease-reveal, var(--rb-sys-ease-expo));
  transition-delay: calc(
    (var(--rbs-reveal-i, 0) + var(--rbs-reveal-li, 0)) * var(--rbs-reveal-stagger, 60ms)
  );
}

/* ==========================================================================
   REDUCED MOTION — gentler, never dead. Entrances only arm while the motion
   level is authored, but the kernel's `ignore` policy can hold that level
   while the OS still asks for reduce: keep the fade, drop travel and blur.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  body[data-rbs-reveal] .is-rbs-armed [data-rbs-rv] {
    opacity: 0;
    transform: none;
    filter: none;
  }
  body[data-rbs-reveal] .is-rbs-armed [data-rbs-rv-split] .rbs-line__inner {
    transform: none;
  }
  body[data-rbs-reveal] .is-rbs-playing [data-rbs-rv] {
    transition: opacity var(--rb-sys-duration-3) var(--rb-sys-ease-out);
    transition-delay: calc(var(--rbs-reveal-i, 0) * var(--rbs-reveal-stagger, 60ms));
  }
  body[data-rbs-reveal] .is-rbs-playing [data-rbs-rv-split] .rbs-line__inner {
    transition: none;
  }
}

/* ==========================================================================
   FAILSAFE — if the motion level leaves `authored` while a section is still
   armed (JS should force-reveal, but belt and braces): nothing stays hidden.
   ========================================================================== */

body:not([data-rbs-motion-level="authored"]) .is-rbs-armed [data-rbs-rv] {
  opacity: 1 !important;
  transform: none !important;
  filter: none !important;
}
body:not([data-rbs-motion-level="authored"]) .is-rbs-armed .rbs-line__inner {
  transform: none !important;
}
