# 幕で現れる画像 — Style Reference
> a poster page on warm paper: heavy uppercase-style heading with one dragged band of yellow, and below it a 16:9 photo hidden behind a grid of paper tiles that peel open along the diagonal, one after another.

**Theme:** light  **Series:** PARTS 097  **World:** 改修した倉庫の展示室公開の告知。写真が紙の幕の向こうから、タイル単位で現れる。

## Concept
A reveal that belongs to the page. The tiles are the same colour as the paper, so a closed frame reads as an empty rectangle on the page and an opening one reads as the page itself peeling away. Each tile opens by collapsing toward its top edge (`scaleY`), and tiles start in diagonal order from the top left with a small random jitter so the front reads as a soft line. The page loads at 50 percent and holds there for four seconds, then ping-pongs with a pause at each end; a click takes over and toggles open / closed. A mono caption prints the reveal percentage and tile count.

## Signature Technique
DOM and CSS only; one JS loop sets one custom property per tile.

- **Grid.** `.tiles` is a CSS grid of `cols x rows` `<i>` elements (16 x 9 desktop, 10 x 9 mobile) absolutely covering the photo. Each tile is a paper-coloured block with `transform: scaleY(var(--s))`, `transform-origin: top`, `will-change: transform`.
- **Delay map.** For tile (c, r), `along = dot(center, direction) / |direction| / sqrt 2` gives a 0..1 position along the chosen sweep direction (default (1, 0.6), diagonal from top left). A seeded hash adds +-`jitter / 2`.
- **Progress to scale.** Global progress p in 0..1. Tile k starts at `delay_k * spread` and takes `dur = (1 - spread) * tileDur + 0.02` to open; `t = smoothstep((p - start) / dur)`, `--s = 1 - t`. Writing only the custom property keeps layout untouched; the browser composites 144 transforms.
- **Quantised updates.** p is rounded to 1/400 and the DOM is touched only when it changes.
- **Drive.** `autoValue(t)` is a trapezoid: hold closed for `pause`, open over `period / 2`, hold open, close. The phase is offset so the sweep passes 0.5 exactly when the intro hold ends. A click sets `auto = false` and eases p toward 0 or 1 with `1 - exp(-2.2 dt)`. Enter and Space do the same for keyboard users (`role="button"`, `tabindex="0"`, live `aria-label`).
- **Loop control.** `IntersectionObserver` and `visibilitychange` stop the loop off screen.
- **Reduced motion.** The auto drive is replaced by a fixed 50 percent frame; click still toggles with the eased move.

## Color Palette
| Token | HEX | Role |
|---|---|---|
| --paper | #f3efe6 | page and tile colour |
| --ink | #141311 | heading, body on paper, stage backdrop behind the photo |
| --mute | #6f6b63 | eyebrow, lead, tag |
| --hair | rgba(20,19,17,.16) | stage border |
| --band | #f2d64b | the single highlighter band behind two words of the heading |

## Typography
- **Noto Sans JP** 300 / 400 / 700. h1 clamp(34px, 4.6vw, 68px) weight 700, letter-spacing -0.03em, line-height 1.05, with a `linear-gradient` highlight on the `<em>`. Lead clamp(14px, 1.05vw, 16px) weight 300, max 34ch.
- **IBM Plex Mono** 400 for the eyebrow (11px, 0.18em, uppercase), the in-frame caption (10px, 0.16em, paper-coloured text on a small ink underlay `rgba(20,19,17,.62)` with a 6px backdrop blur, padding 5px 9px, radius 2px, so it stays legible across tile edges) and the corner tag.

## Spacing & Layout
- Vertical stack: header row (heading left, lead right, `flex-wrap`), then the stage. Padding `clamp(64px, 9vh, 100px)` top, `clamp(90px, 12vh, 140px)` bottom, `clamp(20px, 5vw, 72px)` sides.
- Stage `aspect-ratio: 16 / 9`, `max-height: 62vh`, hairline border, square corners.
- Under 760px: header stacks, stage switches to a 4:5 portrait crop (uncapped), bottom padding 120px, tag bottom left. The tile grid (10 x 9) is chosen once from `innerWidth` at load.

## Motion
- Intro hold 4 s at 50 percent, then period 7 s with 1.2 s pauses at each end.
- Each tile's own opening lasts about 10 percent of the sweep; the diagonal front covers 86 percent, so at the midpoint roughly half the tiles are solid and half are gone.
- Click: eased toggle, `p += (target - p)(1 - exp(-2.2 dt))`, about 1.4 s to reach 95 percent.
- rAF loop, `dt` clamped to 0.1 s.
- `prefers-reduced-motion`: no auto sweep; the frame stays at 50 percent until a click.

## Components
- **head**: eyebrow, two-line heading with a yellow band, lead paragraph.
- **stage**: photo, tile grid, caption (`Reveal 50% / Tiles 144`).
- **tag**: `VALE / PARTS 097 / 幕で現れる画像` plus hint.

## Do / Don't
Do
- Make the tiles the page colour so the closed state is part of the layout.
- Sweep along a diagonal with jitter; a straight row-by-row wipe looks like a loading bar.
- Keep each tile's own motion short and the stagger long.

Don't
- No fades on the tiles; the collapse should be a solid edge.
- No shadows or gaps between tiles.
- No more than about 200 tiles; the loop writes one property per tile per change.

## Usage
1. Wrap the image: `<div class="stage"><img src="..."><div class="tiles" id="tiles"></div></div>` and copy the `.tiles` and `.tiles i` rules. Set `.tiles i { background: <page colour> }`.
2. Copy the `<script>` block. It builds the tiles, computes delays and runs the loop.
3. To trigger on scroll instead of time, set `auto = false` and set `target = 1` from an `IntersectionObserver`; to reveal once, remove the ping-pong (`autoValue`) and ease p from 0 to 1.
4. Tune `P`.

| パラメータ | 既定 | 意味 |
|---|---|---|
| cols, rows | 16 x 9 / 10 x 9(モバイル) | タイル数 |
| spread | 0.86 | 進行のうちスタッガーに使う割合 |
| tileDur | 0.55 | 残りの進行のうち1タイルが開くのに使う割合 |
| direction | (1, 0.6) | 開いていく向き。(0,1) で上から下、(1,0) で左から右 |
| jitter | 0.08 | タイルごとの遅延のばらつき |
| period / pause | 7 / 1.2 | 往復の秒数と両端で止まる秒数 |
| introHold | 4 | 読み込み後に 50% で止める秒数 |

`transform-origin` を `bottom` にすると下へ畳まれ、`scaleX` にすると横に消える。

## References
- **SaveDay** (stock/refero/md/saveday.md): oversize black type on cream with one band of yellow dragged across. Abstracted: paper canvas, heavy heading, the single highlighter band. Changed: the band is a background gradient on two words only, and the motion on the page comes from the opening tiles alone.
- **Klarna ES** (stock/refero/md/klarna-es.md): a dark void opening onto a warm bone floor, oversized geometric type, pill controls. Abstracted: the idea of a dark field opening onto a light one, here inverted (paper opening onto a photo). Changed: no candy colours and no cards; one photo, one band.
