# DESIGN.md — 動く活字 / kinetic-katsuji

> **使い方**: このファイルをプロジェクトに置き、AIに
> 「DESIGN.md に従って◯◯のサイトを作って」と指示してください。
> ライセンス: 商用利用可・改変可・クレジット不要（AIっぽくないデザイン見本帳 / サードパーティートラスト）

## 1. コンセプト

文字は読むものである前に、見るものであり、動くものである。タイプファウンドリの
実験場を装い、白と黒と蛍光橙、装飾ゼロの舞台の上で**活字そのものに動かす**。
統計カウントアップやパララックスで「賑やかに見せる」のではなく、字面（じづら）・
字間・骨格という組版の変数そのものをスクロールとホバーに応答させる。

**キーワード**: 活字 / 実験 / 舞台 / 縁取り / 骨格
**この見た目が向く場面**: タイプファウンドリ・デザインスタジオ・クリエイティブ制作会社・
カルチャー誌・展示企画など、「見た目そのものが専門性の証明になる」業種

## 2. タイポグラフィ

- 主役（巨大グリフ・和文見出し）: Rampart One / ウェイト400（単一）。日本語グリフを含む
  縁取りディスプレイ書体。中央ステージの巨大グリフと、全セクションの h2 見出しに使う
- 見出し補助（欧文・数字の量感）: Archivo Black / ウェイト400（単一・視覚的に極太）。
  英字ラベル・号数・価格・年号など「欧文として組む断片」専用。**日本語グリフを含まない
  ため和文の見出しには使わない**（文字化けの原因になる）
- 本文: Zen Kaku Gothic New / ウェイト400のみ。本文の強調は太字にせず、
  `.fig`（Archivo Black）でのみ数字部分を目立たせる
- 数字用の等幅役: `ui-monospace, "SFMono-Regular", "SF Mono", Menlo, Consolas, monospace`
  （実在の書体名を偽装しないための総称スタック。書体見本の「数字用」架空書体の代役表示にのみ使用）
- 見出しスケール: 巨大グリフ `clamp(120px, 26vw, 340px)` / セクション h2
  `clamp(30px, 4.2vw, 44px)` / 書体見本ABCDEFG `clamp(34px, 6.4vw, 64px)`
- 特記: 欧文断片（号数・年・価格・ウェイト値）は必ず `.fig`（Archivo Black）で組み、
  和文本文の中に埋め込む。英語小見出し（kicker）は「号数＋英字ラベル」の型のみで、
  和文見出しの機械翻訳にしない

## 3. カラー

白・黒・蛍光橙の3色のみ。中間グレーは新規hexを起こさず、**黒/白の不透明度**で
階調をつくる（swiss-precision のような専用グレーhexを追加しない）。

| 役割 | 値 | 使用比率の目安 |
|---|---|---|
| 地（白セクション） | #fdfdfb | 55% |
| 地（反転セクション＝黒） | #141412 | 25%（制作記録・スタジオについて の2節） |
| テキスト（白地の主） | #141412 | — |
| テキスト（白地の弱） | rgba(20,20,18,0.62) | — |
| テキスト（黒地の主） | #fdfdfb | — |
| テキスト（黒地の弱） | rgba(253,253,251,0.65) | — |
| アクセント（蛍光橙） | #ff5c00 | 3%以下・点でのみ |
| 罫線（白地） | rgba(20,20,18,0.15) | — |
| 罫線（黒地） | rgba(253,253,251,0.22) | — |

- 配色ルール: **判定は必ず実際の祖先背景色で行う**（クラス名の安全リストでは判定しない）。
  白地（#fdfdfb系）の上では橙を**文字色として使わない**。許されるのは
  ①ホバー時の下線バー／罫線色の変化 ②「実験中」バッジ（黒文字＋橙背景の極小矩形）
  ③kicker の小さな四角ドット ④選択中ピッカーの下辺4px罫線 の4つ（すべて非テキスト要素）。
  黒地（反転セクション、#141412系）の上でのみ、コントラストが十分に取れるため
  ⑤号数などの小さな数値ラベルの文字色 ⑥ホバー時のテキスト色変化 も許容する
  （下記コントラスト実測を参照）。いずれの背景でも橙を大見出し・本文・面（背景全体）に使わない
- **実測コントラスト（背景色ごとに両方向で確認）**:
  - 弱テキスト rgba(20,20,18,0.62) on #fdfdfb → 約 **4.8:1**（本文小文字に使用可、AA達成）
  - 弱テキスト rgba(253,253,251,0.65) on #141412 → 約 **8.0:1**
  - 橙 #ff5c00 をテキスト色として白地 #fdfdfb に使う場合 → 約 **3.0:1**（小さな文字には
    **不可**。このため白地セクションでは橙を文字色として使わない。`.stage-meta a.trial:hover` や
    `.foot-nav a:hover` は border-color のみを橙にし、文字色は黒のまま変えない実装にしている）
  - 橙 #ff5c00 と黒 #141412 のペア（黒文字×橙背景 の「実験中」バッジ、または黒地に橙文字の
    号数ラベル・ホバー） → 約 **5.96:1**（AA達成。反転セクション内でのみ橙を文字色に使える根拠）
  - 橙の下線バー・ドット・罫線は装飾的な非テキスト要素（3:1基準）として使用し、
    白地での本文の可読性は常に黒／黒の不透明度のペアで担保する

## 4. レイアウト・余白

- コンテンツ最大幅: 960px（単一カラム中央寄せ。12カラムグリッドは使わない。
  スイス系の非対称グリッドと明確に区別するための意図的な選択）
- **「中央の見本＋周辺の仕様」構図をページ全体で反復する**基本ユニット＝ `.stage`：
  1px罫線の枠の中に、上段に左右2つの注記（書体名/役割、ウェイト）、中央に巨大グリフ、
  下段に左右2つの注記（字面率、試用版リンク）を配置する。書体見本の各カードも同じ構図。
- セクション間: 96px（`.block` の上下padding）/ 節の頭に中央寄せの kicker
  （橙の四角ドット＋号数＋英字ラベル）→ 中央寄せ h2 → 中央寄せリード文、を必ず置く
- ヒーローの構成: **ボタンなし。** 実験ノートの一行（`EXPERIMENT LOG — No.048` ＋
  具体的な一文）→ 巨大グリフの舞台 → 今日の一字ピッカー（5つの文字ボタン）の順。
  「特大中央見出し＋サブコピー＋ボタン2つ」の定型を作らない
- 白セクションと黒セクション（反転）を交互に配置し、無彩色のみで十分な差をつくる
  （中間グレーの節区切りを新設しない）

## 5. コンポーネントの質感

- ヘッダー・ナビゲーション: 白地・sticky。ブランドは「活字試験場」の文字のみで、
  ホバーで1字ずつ上下に散って戻る（§9のコード例参照）。ナビリンクはホバーで
  下線バー（橙・4px）がスライドインする。文字色そのものは橙に変えない（§3のコントラスト理由）
- 角丸: 0px（全要素直角、border-radius を使わない）
- 影: 使わない（box-shadow なし。奥行きは1px罫線と余白のみで表現）
- 境界線: **1pxと4pxの2種類のみ**。1px＝通常の区切り・枠。4px＝フッター最上部の罫線、
  選択中ピッカーボタンの下辺、focus-visible の輪郭線。2px・3pxの罫線を作らない
- ボタン的要素: 独立した「ボタン」コンポーネントを持たない。誘導はすべて
  「テキスト＋下線（ホバーで橙に変化）」の形（`.trial` クラス）に統一する
- 今日の一字ピッカー: 52×52px（モバイル44×44px）の正方形ボタン。ホバーで4px浮き上がり
  ＋枠線が橙に。選択中は下辺4pxを橙にして状態を示す（塗りつぶしではなく罫線で示す）
- カード的要素: 罫線で囲んだ `.stage` 枠のみ。角丸カード・影付きカード・3カラム機能紹介
  カードを作らない
- フォーム要素: 本デザインにはフォームを設けない（お問い合わせはテキストリンクのみ）
- 画像の扱い: 写真・イラストを使わない（§7参照）
- アクセント色の適用範囲: §3の4用法に厳密に限定。ナビ・本文・見出しの文字色を
  橙に変える実装をしない

## 6. モーション

- 量: **experimental**。ただし「ランダムに散らかす」ことを許可しない。動きは以下の
  3種類に限定し、すべて **ユーザー操作（クリック・ホバー）かスクロール位置に応答**する。
  タイマーで自走する動き・無限ループ・マーキー・タイプライターは一切使わない
  1. **中央グリフのスクロール連動変形**: ヒーローのグリフが、ヒーローセクションの
     スクロール進捗（0〜1）に応じて `scale` / `skewX` / `rotate` を合成変化させ、
     太さが変わって見える（§9のコード例参照）
  2. **ホバーでの文字分解・再結合**: `.kinetic` クラスの短いテキスト（ブランド名・
     ナビリンク）は1文字ずつ span に分解済みで、ホバー中のみ奇数字/偶数字の2パターンで
     上下＋回転にずれる。マウスが離れると transition で元の位置に戻る（＝再結合）。
     ランダム値は使わず、常に同じ2パターンに揃える（規律を保つ）
  3. **書体見本の階段立ち上がり**: ABCDEFG等の各文字がスクロールで視界に入ったとき、
     `transition-delay` を1文字ずつ70msずつずらして立ち上がる。IntersectionObserver で
     一度だけ発火し、繰り返さない
- 使わない動き: 数字のカウントアップ、無限マーキー、タイプライター、自動カルーセル、
  一定間隔で繰り返すループアニメーション、パララックス
- `prefers-reduced-motion: reduce` では上記すべてを無効化し、最終状態（立ち上がり後の
  文字・変形なしのグリフ）を静的に表示する（§9のコード例参照）

## 7. 写真・イラスト・図版

- 写真・イラストを一切使わない。図版に相当するのは活字のグリフそのもの
  （Rampart One / Archivo Black / 等幅フォントの実際の字形）のみ
- 装飾用のSVG図形・アイコン・絵文字を使わない。誘導の矢印は `→`（U+2192の約物）のみ使用

## 8. 禁止事項（must not）

- Inter / Roboto / system-ui をデフォルトで使わない（Rampart One / Archivo Black /
  Zen Kaku Gothic New の3書体構成を厳守する）
- 紫〜青のグラデーション、グラスモーフィズム（backdrop-filter: blur）、box-shadow による
  発光・浮遊感を一切使わない
- border-radius を使わない（常に0。角丸カード・角丸バッジを作らない）
- 「アイコン＋見出し＋説明の3カラム角丸カード」を作らない。区切りは1px罫線の `.stage` 枠で表現する
- 中央寄せの定型ヒーロー（特大見出し＋サブコピー＋ボタン2つ）を作らない。
  ヒーローにボタンを置かない（誘導は下線付きテキストリンクのみ）
- 統計数字のカウントアップ・無限マーキー・タイプライター・自動ループアニメーションを使わない
  （動きは必ずユーザー操作かスクロール位置への応答であること）
- **Y2K要素（クローム/金属光沢、ワイヤーフレーム球、楕円軌道、ピクセル/液晶表示、
  シルバー基調の地色）を一切使わない。** 本テイストの最近傍は y2k-chrome（距離2）だが、
  白地×黒活字の組版実験であり、金属感・レトロフューチャー感を持ち込まない
- 橙 `#ff5c00` を文字色として白地の通常サイズ本文・ナビ・見出しに使わない
  （実測コントラスト約3.0:1でAA本文基準を満たさないため。§3参照）
- 絵文字をアイコンとして使わない（アイコンが必要な場面でも作らない。矢印は約物の `→` のみ）
- 罫線の太さを1pxと4px以外にしない（2px・3pxの罫線を新設しない）

## 9. 実装ノート

```css
/* tokens.css — この変数セットをそのまま使うこと */
:root {
  --color-bg: #fdfdfb;
  --color-ink: #141412;
  --color-ink-weak: rgba(20, 20, 18, 0.62);   /* 実測 約4.8:1 on --color-bg */
  --color-bg-inverse: #141412;
  --color-paper-inverse: #fdfdfb;
  --color-paper-weak: rgba(253, 253, 251, 0.65); /* 実測 約8.0:1 on --color-bg-inverse */
  --color-accent: #ff5c00;    /* ホバー下線・実験中バッジ・kickerドット・選択枠の4用途限定 */

  --line-hair: rgba(20, 20, 18, 0.15);
  --line-hair-inverse: rgba(253, 253, 251, 0.22);
  --line-heavy: var(--color-ink);
  --line-heavy-inverse: var(--color-paper-inverse);

  --font-display: "Rampart One", sans-serif;      /* 巨大グリフ・全h2見出し（和文グリフ含む） */
  --font-head: "Archivo Black", sans-serif;       /* 欧文・数字の断片専用（和文グリフなし） */
  --font-body: "Zen Kaku Gothic New", sans-serif; /* 本文400のみ */
  --font-mono: ui-monospace, "SFMono-Regular", "SF Mono", Menlo, Consolas, monospace;

  --max-width: 960px;
}
```

フォント読み込み:
`https://fonts.googleapis.com/css2?family=Rampart+One&family=Archivo+Black&family=Zen+Kaku+Gothic+New:wght@400&display=swap`

**中央グリフのスクロール連動変形**（禁止事項の「タイマー自走」ではなく、
scroll イベント駆動であることが要件。rAF でスロットルする）:

```css
.stage-glyph {
  transform: scale(calc(1 + var(--wp, 0) * 0.16))
             skewX(calc(var(--wp, 0) * -5deg))
             rotate(calc(var(--wp, 0) * -1.4deg));
  transition: transform 0.06s linear;
}
```
```js
var ticking = false;
function update() {
  var rect = hero.getBoundingClientRect();
  var vh = window.innerHeight;
  var p = 1 - Math.min(Math.max(rect.top / vh, 0), 1); // 0..1
  glyph.style.setProperty("--wp", p.toFixed(3));
  ticking = false;
}
window.addEventListener("scroll", function () {
  if (!ticking) { requestAnimationFrame(update); ticking = true; }
}, { passive: true });
```

**文字分解ホバー（規律=2状態のみ。ランダム値を使わない）**:

```css
.kinetic .ch { display: inline-block; transition: transform 0.32s cubic-bezier(.2,.8,.2,1); }
.kinetic:hover .ch:nth-child(odd)  { transform: translateY(-0.16em) rotate(-5deg); }
.kinetic:hover .ch:nth-child(even) { transform: translateY(0.14em) rotate(4deg); }
```

**reduced-motion対応（必須）**:

```css
@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.001ms !important; transition-delay: 0ms !important; }
  .stage-glyph { transform: none !important; }
  .specimen-row .ch { opacity: 1 !important; transform: none !important; }
  .kinetic:hover .ch { transform: none !important; }
}
```

- 判定は必ず「実際の祖先背景色」で行うこと。本デモでは `.block.inverse` 配下は黒地なので
  橙・白のコントラストペアに切り替わる。クラス名を安全リストとして丸暗記せず、
  実際にレンダリングした背景色に対して都度コントラストを確認すること
- Archivo Black は日本語グリフを持たない欧文専用フォントであるため、和文テキストに
  指定すると文字が欠落表示になる。`.fig` クラスは必ず半角英数字の断片にのみ付与すること

**弱色・罫線トークンの反転（inverse）対応チェックリスト（tier-B指摘 2026-07-11 対応）**:

`.block.inverse`（#log・#studio）配下で `--color-ink-weak` / `--line-hair` を
そのまま使うと黒地に埋没する。白地用トークンを使う箇所には必ず反転版
（`--color-paper-weak` / `--line-hair-inverse`）の上書きを対にすること。
新しいコンポーネントを追加するたびに以下を確認する:

| セクション | 要素 | 白地用トークン | 反転オーバーライド | 状態 |
|---|---|---|---|---|
| #log | `.kicker` / `.sec-head p` | `--color-ink-weak` | `.block.inverse .kicker` / `.block.inverse .sec-head p` → `--color-paper-weak` | 済 |
| #log | `.log-entry` 罫線 | `--line-hair` | `.log-entry` 自体に直接 `--line-hair-inverse` を指定（#logのみで使う要素のため） | 済 |
| #log | `.log-date` / `.log-body p` | `--color-ink-weak` | 直接 `--color-paper-weak` を指定 | 済 |
| #studio | `.fact dt` | `--color-ink-weak` | `.block.inverse .fact dt` → `--color-paper-weak`（実測 約8.1:1） | 修正済（旧: 未上書きで約1.9:1・視認不可） |
| #studio | `.facts` / `.fact` 罫線 | `--line-hair` | `.block.inverse .facts, .block.inverse .fact` → `--line-hair-inverse` | 修正済 |
| #studio | `.studio-contact a.trial` 下線 | `--color-ink` | `.block.inverse .studio-contact a.trial` → `--color-paper-inverse`（実測 約18:1）。hover時は `.block.inverse .studio-contact a.trial:hover` を別途定義し `--color-accent` を維持（優先度を平常時の上書きより高くするため） | 修正済 |

`.facts`/`.fact` の罫線はテキストではなく装飾区切り線のため4.5:1基準の対象外だが、
`--line-hair-inverse`（白 22%）を使うことで #log の罫線と同一の見え方に統一している。
