# Reveal that never leaves blanks (`reveal-safe`)

Staggered scroll reveals with guarantees: nothing on screen at load is ever hidden, stagger is capped at 5 × 60 ms, and anything you flick past, jump to or print is simply there.

| | |
|---|---|
| Tag | Flow |
| Size | 1.6 KB gzipped own code (JS 1.4 KB + CSS 0.3 KB; 3.8 KB raw) |
| Dependency | none (vanilla + native APIs) |
| Best for | Every preview: price rows, service lists, gallery sets, team cards |
| Demo | `index.html` in this folder (live: https://wbl-code-lib.pages.dev/modules/reveal-safe/) |

## What it does
Elements below the fold get a hidden start state only after JS measured them (no flash, no CLS, no hidden hero). Items entering the viewport together stagger by DOM order, counted per batch (a 20-row list never waits 1.2 s). Items scrolled past while hidden, a #hash jump, a print, a tab coming back or a 2.5 s scroll pause all show pending items instantly. Rise is 18 px over 0.5 s (under the skill's 0.6 s cap).

## When to use
- Instead of a generic 'fade everything in' library (AOS-style), which is where blank screens and invisible-on-arrival content come from (motion_feel cap: stuck-hidden content).
- Lists, card sets, gallery grids, section headings.

## Don't
- On the hero or LCP image (it would be ignored anyway when on screen at load).
- Long rises or blur-ins; more than one reveal style per page.
- Combine with batch 1's stagger on the same elements.

## Reduced motion, no JS, accessibility
- Reduced motion: does nothing at all (no hidden state is ever added).
- No JS: nothing hidden (the start class is added by JS).
- Hidden items are opacity-only, so screen readers and find-in-page still reach them; the failsafe shows them anyway.

## Notes
- WBL.reveal.refresh() after inserting content; WBL.reveal.flush() shows everything.

## Relation to the effects libraries
Batch 1's stagger animates sets on entry; this one adds the safety rules that our motion checker flags (hidden-on-arrival, long waits).

## Use it
Copy this folder to the site as `/wbl/reveal-safe/` (keep `vendor/` if there is one), then:

```html
<!-- Reveal that never leaves blanks (WBL Code Library) -->
<!-- in <head>: -->
<script>document.documentElement.classList.add('wbl-js')</script>
<link rel="stylesheet" href="/wbl/reveal-safe/module.css">
<script src="/wbl/reveal-safe/module.js" defer></script>

<!-- markup: -->
<!-- one element -->
<h2 data-wbl="reveal">Prices</h2>

<!-- a set: children arrive in a short stagger (only those entering together) -->
<ul class="rows" data-wbl="reveal-group">
  <li><b>Women's cut + blow-dry</b><span class="pr">$65</span></li>
  <li><b>Men's cut</b><span class="pr">$40</span></li>
  <li><b>Gloss / toner</b><span class="pr">$55</span></li>
</ul>
```

Colours come from CSS variables with safe defaults: `--wbl-accent`, `--wbl-on-accent`, `--wbl-ink`, `--wbl-paper`,
`--wbl-card`, `--wbl-line`, `--wbl-muted`, `--wbl-band`, `--wbl-radius`, `--wbl-head` (see the library README for the
one-line bridge to the preview builder's `--a / --ink / --bg …`).

## License
Our code: WBL-owned, original. No third-party code.
