# 雨 — Style Reference
> 夜の路上に降る雨。街灯の下だけ筋が暖色に光り、濡れた地面に映る

**Theme:** dark  **Series:** PARTS 040  **World:** 架空の雨音アプリ「Shizuku」のトップ。音の代わりに、雨粒の落下と地面での跳ねをそのまま見せる。

## Concept
画面全体が夜の雨。5,184 本の雨粒が GPU 上で落ち、地面(高さ 86%)に当たった瞬間、その位置から小さな雫が2つ跳ねる。奥の雨は細く遅く短く、手前の雨は太く速く長い。右上に街灯が1つあり、その近くを通る筋と雫だけ暖色に光る。地面は濡れていて、筋と街灯が薄く映る。カーソルの左右で風が付き、筋が斜めになる。

## Signature Technique
GPGPU 粒子 3 系統(雨粒 1、跳ね 2)と、線分による筋の描画。

1. **雨粒テクスチャ**: 一辺 `side`(72、モバイル 44)の RGBA float。`x, y`=位置(画面高さ=1)、`z`=落下速度(0.9–2.6、遅い=奥)、`w`=着地フラグ。
   ```glsl
   if (flag) { x = hash·(aspect+0.6) − 0.3; y = −hash·0.4; flag = 0; }      // 着地の次のフレームで上へ戻す
   else { y += speed·dt; x += wind·speed·0.35·dt; if (y >= ground) { y = ground; flag = 1; } }
   ```
2. **跳ねテクスチャ ×2**(A/B): 雨粒と同じ uv の texel が、その雨粒の `flag` が立った瞬間に `(x, ground)` から `vx = ±0.22·rand·(0.4 + 0.6·speed/2.6)`、`vy = −(0.35〜0.65)·(0.5 + 0.5·speed/2.6)` で生まれ(速い手前の雨ほど高く跳ねる)、重力 2.4 で落ちて地面より下に出たら止まる(`y > ground` を「停止」として使う)。更新順は 跳ね → 雨粒。
3. **筋の描画**: 雨粒 1 つにつき 2 頂点(頭と尾)を `gl.LINES` で描く。尾は `p − (wind·speed·0.35, speed)·streak·(0.4 + near)`。`near = smoothstep(0.9, 2.6, speed)`。alpha は頭 `0.42·mix(0.25, 1, near)`、尾はその 15%(線形補間で先細りに見える)。
4. **街灯**: `lampK = smoothstep(r, 0, |(p − lamp)·(1, 1.4)|)`。色を `mix(ink, amber, 0.9·lampK)·(1 + 1.2·lampK)` にして近い筋ほど明るく暖かい。
5. **雫の描画**: 跳ねは `gl.POINTS`、径 2.2px(モバイル 1.8px)× dpr、alpha 0.55、縁 `smoothstep(.2,.5,d)`。alpha に `smoothstep(ground, ground−.03, y+.03)` を掛け、地面から 0.03 より高く跳ねた分だけ見せる(0.06 で不透明)。
6. **映り込み**: `uMirror=1` でもう一度描く。`y' = 2·ground − y`、尾は地面で切り、明るさ 0.2。
7. **背景**: 上 `#2a3744` → 地面 `#0b0e14` の縦グラデーション、地面は 80% の暗さ、街灯の放射光、地面に街灯の縦の映り、地面の縁に細い光沢(`top·0.25`、地面から 0.06 の幅)。
8. 起動時に 40 ステップ回してから描く(最初から雨が降っている)。IntersectionObserver と visibilitychange で画面外停止。

## Color Palette
| Token | HEX | Role |
|---|---|---|
| --night | #0b0e14 | 地面と画面下部。背景グラデーションの終点 |
| --dusk | #2a3744 | 空(背景グラデーションの始点)、地面の縁の光沢 |
| --white | #ffffff | 見出し、ブランド名、クレジット |
| --mist | #b5b5b5 | 本文 |
| --smoke | #7a7f88 | ヘッダーのラベル、操作説明 |
| (ink) | #d8e0ea | 筋と雫の基本色(JS 内) |
| --lamp | #ffb45c | 街灯、その近くの筋と雫、読み出しの区切り点 |

## Typography
- 日本語見出し: Noto Sans JP 400、`clamp(20px, 1.8vw, 26px)`、letter-spacing −0.01em、line-height 1.45。
- 本文: Noto Sans JP 300、`clamp(13px, 1.05vw, 15px)`、最大幅 30em。雨粒数は JS で実測。
- ラベル: JetBrains Mono 400、11–12px、letter-spacing 0.06–0.08em。風の値は `wind +0.3` の形式で 16 フレームごとに更新。
- WebGL 不可時は `.fallback` にブランド名を Inter 300 で出す。

## Spacing & Layout
- hero `min-height: 100svh`、3行グリッド。canvas は背面全面。
- 余白: 横 `clamp(20px, 5vw, 72px)`、上 `clamp(20px, 3vw, 40px)`、下 `clamp(18px, 2.6vw, 32px)`。モバイル左右 18px。
- 地面は高さ 86%。見出しと本文はその下(濡れた地面の上)に置く。街灯は `x = 0.78·aspect`、`y = 0.3`、半径 0.42(縦長では x = 0.7·aspect、半径 ×0.7)。
- breakpoint 760px: ブランド横の説明を消し、フッターを縦積み。

## Motion
- 落下 0.9–2.6(画面高さ/秒)。筋の長さは速度 × 0.034 × (0.4–1.4)。
- 風はカーソルの横位置で −0.5〜+0.5、毎秒 2 の一次遅れで追う。離すと 0 へ戻る。
- 跳ねは上向き初速 0.35–0.65、重力 2.4 で 0.3–0.5 秒。
- `prefers-reduced-motion: reduce`: rAF を回さず、40 ステップ進めた1枚だけ描く。筋と雫の静止画になる。

## Components
- hero: 背面 canvas(`aria-hidden`)+前面テキスト。テキスト層は `pointer-events: none`。
- header: 左にブランド名、右に `5,184 drops · wind +0.0`。区切り点だけ暖色。
- copy: 見出し1行+本文2文。
- footer tag: `VALE / PARTS 040 / 雨` と操作説明1行(タッチ端末では文言差し替え)。

## Do / Don't
- Do: 速度を奥行きとして使い、太さと長さと明るさを同じ変数から決める。奥行きが出る。
- Do: 暖色は街灯の近くだけ。画面全体を暖めると夕方になる。
- Do: 跳ねは 2 個で足りる。4 個以上は地面が白い帯になる。
- Don't: 雨粒を 1 万本以上にしない。壁になって地面が見えない。
- Don't: 筋を線幅 2px 以上にしない(WebGL の LINES は 1px)。太くしたいなら手前だけ四角形で描く。
- Don't: 地面を消さない。跳ねと映り込みが雨を雨にしている。

## References
- Tatem: 青灰から炭色への1本のグラデーションに、暖色の光を1点だけ置く構造を借りた。光を街灯にし、雨粒の色にも反映させた。
- HBO Max: 黒い壁に青い非常灯1つという「闇の中の1点の光」の考え方を借りた。青灯を暖色の街灯に変え、雨の筋で光を見せた。

## Usage
1. `<main id="hero">` の中に `<canvas id="gl">` を置く(canvas は `position:absolute; inset:0`)。スクリプトは `#hero` の大きさで解像度を決め、`#hero` でタッチと pointerleave を受ける。フォントは任意。
2. `<script>` ブロック全体を移植する。`boot()` が3系統のテクスチャを作り、40 ステップ回してから描き始める。
3. 地面の高さは `P.ground`。テキストを地面より下に置くとき、見出しの上端が `ground` より下になるよう余白を調整する。
4. 街灯は `P.lamp` と `lamp()`。不要なら `P.lamp.r = 0` にする。
5. 色は `ink` / `acc` / `top` / `bot` を CSS 変数と揃える。読み出し(`#n`、`#w`)が不要なら消す。

| パラメータ | 既定 | 意味 |
|---|---|---|
| side | 72 / 44(モバイル) | 雨粒テクスチャの一辺。雨粒数は side²、跳ねはその 2 倍 |
| ground | 0.86 | 地面の高さ(画面高さ比) |
| speed | [0.9, 2.6] | 落下速度の範囲。奥→手前 |
| streak | 0.034 | 筋の長さ(速度に掛ける) |
| windMax | 0.5 | カーソルで付く風の最大値 |
| splash.vx / vy / g | 0.22 / [0.35, 0.65] / 2.4 | 跳ねの横速度と上向き初速と重力 |
| lamp.x / y / r | 0.78 / 0.3 / 0.42 | 街灯の位置(x は aspect 比)と届く半径 |
| alpha / reflect | 0.42 / 0.2 | 筋の明るさ、映り込みの明るさ |
| dprMax | 2 | 表示解像度の上限 |

雪にしたい場合は `speed` を [0.1, 0.3]、`streak` を 0、跳ねの `vy` を [0, 0] にし、点で描く。
